home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Applications / NIH Image 1.60 / 1.60 Source / File1.p < prev    next >
Encoding:
Text File  |  1996-03-01  |  95.2 KB  |  3,470 lines  |  [TEXT/PJMM]

  1. unit File1;
  2.  
  3. {Routines used by NIH Image for implementing File Menu commands.}
  4.  
  5. interface
  6.  
  7.  
  8.     uses
  9.         Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, 
  10.         Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows,
  11.         Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, Processes,
  12.         globals, Utilities, Graphics, file2, Dicom, sound, Lut, Text;
  13.  
  14.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  15.     procedure DoClose;
  16.     function OpenFile (fname: str255; vnum: integer): boolean;
  17.     function OpenPict (fname: str255; vnum: integer; Reverting: boolean): boolean;
  18.     procedure SaveFile;
  19.     function DoOpen (FileName: str255; RefNum: integer): boolean;
  20.     function ImportFile (FileName: str255; RefNum: integer): boolean;
  21.     procedure RevertToSaved;
  22.     procedure SaveAs (name: str255; RefNum: integer);
  23.     procedure Export (name: str255; RefNum: integer);
  24.     procedure FindWhatToPrint;
  25.     procedure UpdateFileMenu;
  26.     procedure SaveAsText (fname: str255; RefNum: integer);
  27.     procedure SaveAll;
  28.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  29.     procedure RescaleToEightBits;
  30.  
  31.  
  32. implementation
  33.  
  34.     var
  35.         OpenAllFiles, UseExistingLUT, PICTReadErr: boolean;
  36.         SaveRefNum: integer;
  37.         TempStackInfo: StackInfoRec;
  38.         PictSrcRect: rect;
  39.  
  40. {$PUSH}
  41. {$D-}
  42.  
  43.     procedure LookForCluts (fname: str255; vnum: integer);
  44.         var
  45.             RefNum: integer;
  46.             err: OSErr;
  47.             ok1, ok2: boolean;
  48.     begin
  49.         if not UseExistingLUT then begin
  50.                 err := SetVol(nil, vnum);
  51.                 refNum := OpenResFile(fname);
  52.                 if RefNum <> -1 then begin
  53.                         ok1 := LoadCLUTResource(KlutzID);
  54.                         if not ok1 then
  55.                             ok2 := LoadCLUTResource(PixelPaintID);
  56.                         CloseResFile(refNum);
  57.                     end;
  58.             end;
  59.     end;
  60.  
  61.  
  62.  
  63.     function OpenImageHeader (f: integer; fname: str255; vnum: integer): boolean;
  64.         var
  65.             ByteCount: LongInt;
  66.             err: OSErr;
  67.             TempHdr: PicHeader;
  68.             i, OldNExtra, p1x, p2x: integer;
  69.             ok: boolean;
  70.             hUnitsKind: UnitsType;
  71.     begin
  72.         if SizeOf(PicHeader)<>HeaderSize then begin
  73.             PutError(StringOf('Internal error (size= ', SizeOf(PicHeader):1,')'));
  74.             OpenImageHeader := false;
  75.             exit(OpenImageHeader);
  76.         end;
  77.         ByteCount := HeaderSize;
  78.         err := SetFPos(f, fsFromStart, info^.HeaderOffset);
  79.         err := fsread(f, ByteCount, @TempHdr);
  80.         if CheckIO(err) <> NoErr then begin
  81.                 OpenImageHeader := false;
  82.                 exit(OpenImageHeader);
  83.             end;
  84.         with info^, TempHdr do begin
  85.                 if PictureType <> TiffFile then begin
  86.                         nlines := hnlines;
  87.                         PixelsPerLine := hPixelsPerLine;
  88.                     end;
  89.                 if (hversion > 54) and not UseExistingLUT then begin
  90.                         OldNExtra := nExtraColors;
  91.                         nExtraColors := hnExtraColors;
  92.                         ExtraColors := hExtraColors;
  93.                         if (nExtraColors > 0) or (OldNExtra <> nExtraColors) then
  94.                             RedrawLUTWindow;
  95.                     end;
  96.                 if (hversion >= 42) and not UseExistingLUT then begin
  97.                         if hversion < 142 then begin
  98.                                 LUTMode := hOldLUTMode;
  99.                                 if (LutMode = OldAppleDefault) or (LutMode = OldSpectrum) then
  100.                                     LutMode := ColorLut;
  101.                             end
  102.                         else begin
  103.                                 LUTMode := hLUTMode;
  104.                                 if LutMode = Pseudocolor then begin
  105.                                         if ((hnColors > 32) and (hTable = CustomTable)) or (hTable > spectrum) then
  106.                                             LutMode := ColorLut;
  107.                                     end;
  108.                             end;
  109.                         case LUTMode of
  110.                             PseudoColor: 
  111.                                 if hversion < 142 then begin
  112.                                         nColors := hOldnColors;
  113.                                         for i := 0 to ncolors - 1 do begin
  114.                                                 RedLUT[i] := hr[i];
  115.                                                 GreenLUT[i] := hg[i];
  116.                                                 BlueLUT[i] := hb[i];
  117.                                             end;
  118.                                         ColorEnd := 255 - hOldColorStart;
  119.                                         ColorStart := ColorEnd - nColors * hColorWidth + 1;
  120.                                         if ColorStart < 0 then
  121.                                             ColorStart := 0;
  122.                                         InvertPalette;
  123.                                         FillColor1 := BlackRGB;
  124.                                         FillColor2 := BlackRGB;
  125.                                         ColorTable := CustomTable;
  126.                                         UpdateLUT;
  127.                                     end
  128.                                 else begin {V1.42 or later}
  129.                                         if (hTable <> CustomTable) and (hTable <= spectrum) then begin
  130.                                                 SwitchColorTables(GetColorTableItem(hTable), false);
  131.                                                 if hInvertedTable then
  132.                                                     InvertPalette;
  133.                                             end
  134.                                         else begin
  135.                                                 nColors := hnColors;
  136.                                                 ColorTable := CustomTable;
  137.                                                 if nColors <= 32 then
  138.                                                     for i := 0 to ncolors - 1 do begin
  139.                                                             RedLUT[i] := hr[i];
  140.                                                             GreenLUT[i] := hg[i];
  141.                                                             BlueLUT[i] := hb[i];
  142.                                                         end;
  143.                                             end;
  144.                                         ColorStart := hColorStart;
  145.                                         ColorEnd := hColorEnd;
  146.                                         FillColor1 := hFill1;
  147.                                         FillColor2 := hFill2;
  148.                                         UpdateLUT;
  149.                                         UpdateMap;
  150.                                     end; {v1.42 or later}
  151.                             GrayScale: 
  152.                                 ResetGrayMap;
  153.                             ColorLut, CustomGrayscale: 
  154.                                 if PictureType <> PictFile then begin
  155.                                         if ColorMapOffset > 0 then
  156.                                             GetTiffColorMap(f)
  157.                                         else
  158.                                             LookForCluts(fname, vnum);
  159.                                     end;
  160.                             otherwise
  161.                         end; {case}
  162.                         if hLutMode = CustomGrayscale then
  163.                             LutMode := CustomGrayscale;
  164.                     end;{if}
  165.                 if (hversion >= 65) and ((ForegroundIndex <> hForegroundIndex) or (BackgroundIndex <> hBackgroundIndex)) then begin
  166.                         SetForegroundColor(hForegroundIndex);
  167.                         SetBackgroundColor(hBackgroundIndex);
  168.                     end;
  169.                 if (hversion > 88) and (LUTMode = GrayScale) and not UseExistingLUT then begin
  170.                         if hversion < 138 then begin
  171.                                 p1x := 255 - hp2x;
  172.                                 p2x := 255 - hp1x;
  173.                             end
  174.                         else begin
  175.                                 p1x := hp1x;
  176.                                 p2x := hp2x
  177.                             end;
  178.                         nColors := 256;
  179.                         ColorStart := p1x;
  180.                         ColorEnd := p2x;
  181.                         UpdateLUT;
  182.                     end;
  183.                 if hversion > 106 then begin
  184.                         {xScale := hXScale;} {68k-bug}
  185.                         xScale := DoubleToReal(hXScale);
  186.                         yScale := xScale;
  187.                         PixelAspectRatio := 1.0;
  188.                         SpatiallyCalibrated := xScale <> 0.0;
  189.                     end;
  190.                 if hversion > 140 then begin
  191.                         PixelAspectRatio := hPixelAspectRatio;
  192.                         yScale := xScale / PixelAspectRatio;
  193.                     end;
  194.                 if hversion > 153 then
  195.                     xUnit := hXUnit
  196.                 else begin
  197.                         hUnitsKind := UnitsType(hUnitsID - 5);
  198.                         GetXUnits(hUnitsKind);
  199.                     end;
  200.                 if xUnit = 'pixel' then
  201.                     SpatiallyCalibrated := false;
  202.                 if ((hnCoefficients > 0) and (hfit < Uncalibrated)) or (hfit = UncalibratedOD) then begin
  203.                         if hfit = SpareFit1 then begin
  204.                                 fit := uncalibrated;
  205.                                 DrawLabels('', '', '');
  206.                             end
  207.                         else begin
  208.                                 fit := hfit;
  209.                                 if hfit <> UncalibratedOD then begin
  210.                                         nCoefficients := hnCoefficients;
  211.                                         for i:=1 to maxCoeff do
  212.                                             {Coefficient[i] := hCoeff[i];} {68k-bug}
  213.                                             Coefficient[i]:=DoubleToReal(hCoeff[i]);
  214.                                         nKnownValues := 0;
  215.                                     end;
  216.                                 UnitOfMeasure := hUM;
  217.                                 if hversion >= 144 then
  218.                                     ZeroClip := hZeroClip
  219.                                 else
  220.                                     ZeroClip := false;
  221.                             end;
  222.                     end
  223.                 else begin
  224.                         fit := uncalibrated;
  225.                         DrawLabels('', '', '');
  226.                     end;
  227.                 BinaryPic := hBinaryPic;
  228.                 if hSliceEnd > 1 then begin
  229.                         SliceStart := hSliceStart;
  230.                         SliceEnd := hSliceEnd;
  231.                         if SliceEnd > 254 then
  232.                             SliceEnd := 254;
  233.                     end;
  234.                 if hNSlices > 1 then begin
  235.                         with TempStackInfo do begin
  236.                                 nSlices := hNSlices;
  237.                                 if nSlices > MaxSlices then
  238.                                     nSlices := MaxSlices;
  239.                                 CurrentSlice := hCurrentSlice;
  240.                                 if (hCurrentSlice < 1) or (hCurrentSlice > nSlices) then
  241.                                     CurrentSlice := 1;
  242.                                 SliceSpacing := hSliceSpacing;
  243.                                 FrameInterval := hFrameInterval;
  244.                                 StackType := VolumeStack;
  245.                                 if hVersion >= 158 then
  246.                                     StackType := hStackType;
  247.                             end;
  248.                     end;
  249.                 FileVersion := hVersion;
  250.                 OpenImageHeader := true
  251.             end;
  252.     end;
  253.  
  254.  
  255.     function OpenHeader (f: integer; fname: str255; vnum: integer; var TiffInfo: TiffInfoRec): boolean;
  256.         var
  257.             ByteCount, FileSize, DirOffset, MaxImages: LongInt;
  258.             hdr: packed array[1..512] of byte;
  259.             err: OSErr;
  260.             TempHdr: PicHeader;
  261.     begin
  262.         with info^ do begin
  263.                 if (WhatToOpen = OpenUnknown) or (WhatToOpen = OpenImported) then begin
  264.                         err := SetFPos(f, fsFromStart, 0);
  265.                         ByteCount := 8;
  266.                         err := fsread(f, ByteCount, @hdr);
  267.                         if ((hdr[1] = 73) and (hdr[2] = 73)) or ((hdr[1] = 77) and (hdr[2] = 77)) then
  268.                             WhatToOpen := OpenTIFF
  269.                         else if WhatToOpen = OpenUnknown then
  270.                             WhatToOpen := OpenImage
  271.                         else
  272.                             WhatToOpen := OpenMCID;
  273.                     end;
  274.                 StackInfo := nil;
  275.                 with TempStackInfo do begin
  276.                         nSlices := 0;
  277.                         CurrentSlice := 1;
  278.                         SliceSpacing := 0.0;
  279.                         FrameInterval := 0.0;
  280.                     end;
  281.                 fileVersion := 0;
  282.                 case WhatToOpen of
  283.                     OpenImage:  begin
  284.                             err := SetFPos(f, fsFromStart, 0);
  285.                             ByteCount := 8;
  286.                             err := fsread(f, ByteCount, @TempHdr);
  287.                             if TempHdr.FileID = FileID8 then begin
  288.                                     HeaderOffset := 0;
  289.                                     PictureType := normal
  290.                                 end
  291.                             else begin
  292.                                     HeaderOffset := -1;
  293.                                     BlockMove(@TempHdr, @hdr, 8);
  294.                                     nlines := hdr[1] + hdr[2] * 256;
  295.                                     PixelsPerLine := hdr[3] + hdr[4] * 256;
  296.                                     PictureType := Imported;
  297.                                     InvertedImage := true;
  298.                                 end;
  299.                             ImageDataOffset := 512;
  300.                         end;
  301.                     OpenMCID:  begin
  302.                             err := SetFPos(f, fsFromStart, 0);
  303.                             ByteCount := 4;
  304.                             err := fsread(f, ByteCount, @hdr);
  305.                             PixelsPerLine := hdr[1] + hdr[2] * 256 + 1;
  306.                             if PixelsPerLine > MaxLine then begin
  307.                                     beep;
  308.                                     PixelsPerLine := MaxLine;
  309.                                 end;
  310.                             nlines := hdr[3] + hdr[4] * 256 + 1;
  311.                             PictureType := imported;
  312.                             LUTMode := grayscale;
  313.                             HeaderOffset := -1;
  314.                             ImageDataOffset := 4;
  315.                         end;
  316.                     OpenCustom:  begin
  317.                             err := GetEof(f, FileSize);
  318.                             if macro then begin
  319.                                     if (ImportCustomOffset + ImportCustomWidth * ImportCustomHeight) > FileSize then begin
  320.                                             AbortMacro;
  321.                                             OpenHeader := false;
  322.                                             exit(OpenHeader)
  323.                                         end;
  324.                                 end;
  325.                             PixelsPerLine := ImportCustomWidth;
  326.                             nlines := ImportCustomHeight;
  327.                             PictureType := imported;
  328.                             HeaderOffset := -1;
  329.                             ImageDataOffset := ImportCustomOffset;
  330.                             if ImportCustomSlices > 1 then
  331.                                 with TempStackInfo do begin
  332.                                         nSlices := ImportCustomSlices;
  333.                                         MaxImages := (FileSize - ImportCustomOffset) div (ImportCustomWidth * ImportCustomHeight);
  334.                                         if nSlices > MaxImages then
  335.                                             nSlices := MaxImages;
  336.                                         if nSlices < 2 then
  337.                                             nSlices := 0;
  338.                                     end;
  339.                         end;
  340.                     OpenPICT2:  begin
  341.                             err := SetFPos(f, fsFromStart, 0);
  342.                             ByteCount := 8;
  343.                             err := fsread(f, ByteCount, @TempHdr);
  344.                             if TempHdr.FileID = FileID8 then
  345.                                 HeaderOffset := 0
  346.                             else
  347.                                 HeaderOffset := -1;
  348.                             PictureType := PictFile;
  349.                             if not UseExistingLUT then
  350.                                 LutMode := ColorLut;
  351.                             ImageDataOffset := 512;
  352.                         end;
  353.                     OpenTIFF:  begin
  354.                             if not OpenTiffHeader(f, DirOffset) then begin
  355.                                     OpenHeader := false;
  356.                                     exit(OpenHeader)
  357.                                 end;
  358.                             if not OpenTiffDirectory(f, DirOffset, TiffInfo, false) then begin
  359.                                     OpenHeader := false;
  360.                                     exit(OpenHeader)
  361.                                 end;
  362.                             with TiffInfo do begin
  363.                                     PictureType := TiffFile;
  364.                                     PixelsPerLine := width;
  365.                                     nlines := height;
  366.                                     if BitsPerPixel = 4 then
  367.                                         PictureType := FourBitTiff;
  368.                                     ImageDataOffset := OffsetToData;
  369.                                     InvertedImage := ZeroIsBlack and (PictureType <> FourBitTIFF);
  370.                                     if resolution > 0.0 then begin
  371.                                             case ResUnits of
  372.                                                 tNoUnits: 
  373.                                                     xUnit := 'pixel';
  374.                                                 tCentimeters: 
  375.                                                     xUnit := 'cm';
  376.                                                 tInches: 
  377.                                                     xUnit := 'inch';
  378.                                             end;
  379.                                             xScale := resolution;
  380.                                             yScale := resolution;
  381.                                             PixelAspectRatio := 1.0;
  382.                                             if xUnit <> 'pixel' then
  383.                                                 SpatiallyCalibrated := true;
  384.                                         end;
  385.                                     ColorMapOffset := OffsetToColorMap;
  386.                                     HeaderOffset := OffsetToImageHeader;
  387.                                 end;
  388.                             if not UseExistingLUT then
  389.                                 LutMode := Grayscale;
  390.                         end;
  391.                 end; {case}
  392.                 if HeaderOffset <> -1 then begin
  393.                         if not OpenImageHeader(f, fname, vnum) then begin
  394.                                 OpenHeader := false;
  395.                                 exit(OpenHeader)
  396.                             end
  397.                     end
  398.                 else if (ColorMapOffset > 0) and not UseExistingLUT then
  399.                     GetTiffColorMap(f);
  400.             end; {with}
  401.         OpenHeader := true;
  402.     end;
  403.  
  404.  
  405.  
  406.     function SaveHeader (f, slines, sPixelsPerLine, vnum: integer; fname: str255; SavingSelection, SavingTIFF: boolean): OSErr;
  407.         var
  408.             TempHdr: PicHeader;
  409.             DummyHdr: array[1..128] of LongInt;
  410.             i: integer;
  411.             ByteCount: LongInt;
  412.             position: LongInt;
  413.             err: OSErr;
  414.             str: str255;
  415.             UnitsKind: UnitsType;
  416.             UnitsPerCM: extended;
  417.     begin
  418.         with TempHdr, info^ do begin
  419.                 for i := 1 to 128 do
  420.                     DummyHdr[i] := 0;
  421.                 BlockMove(@DummyHdr, @TempHdr, HeaderSize);
  422.                 FileID := FileID8;
  423.                 hnlines := nlines;
  424.                 hPixelsPerLine := PixelsPerLine;
  425.                 hversion := version;
  426.                 hLUTMode := LUTMode;
  427.                 hOldLutMode := LutMode;
  428.                 hnColors := ncolors;
  429.                 hOldnColors := 0;
  430.                 if LutMode = Pseudocolor then begin
  431.                         hOldLutMode := ColorLut;
  432.                         if (ColorTable = CustomTable) and (ncolors <= 32) then
  433.                             for i := 0 to nColors - 1 do begin
  434.                                     hr[i] := RedLUT[i];
  435.                                     hg[i] := GreenLUT[i];
  436.                                     hb[i] := BlueLUT[i];
  437.                                 end;
  438.                     end;
  439.                 hColorStart := ColorStart;
  440.                 hColorEnd := ColorEnd;
  441.                 hFill1 := FillColor1;
  442.                 hFill2 := FillColor2;
  443.                 hTable := ColorTable;
  444.                 hInvertedTable := InvertedColorTable;
  445.                 hOldColorStart := 255 - ColorEnd;
  446.                 if nColors > 0 then
  447.                     hColorWidth := (ColorEnd - ColorStart) div nColors
  448.                 else
  449.                     hColorWidth := 1;
  450.                 hnExtraColors := nExtraColors;
  451.                 hExtraColors := ExtraColors;
  452.                 hForegroundIndex := ForegroundIndex;
  453.                 hBackgroundIndex := BackgroundIndex;
  454.                 {hXScale := xScale;} {68k-bug}
  455.                 RealToDouble(xScale, hXScale);
  456.                 hScaleMagnification := 1.0;
  457.                 hPixelAspectRatio := PixelAspectRatio;
  458.                 hUnitsID := 14; {Pixels. For backward compatibility only since hUnits no longer used.}
  459.                 if SpatiallyCalibrated then begin
  460.                         GetUnitsKind(UnitsKind, UnitsPerCM);
  461.                         hUnitsID := ord(UnitsKind) + 5;
  462.                         if hUnitsID > 14 then
  463.                             hUnitsID := 14;
  464.                     end;
  465.                 FindPoints(hp1x, hp1y, hp2x, hp2y);
  466.                 if fit = uncalibrated then
  467.                     hnCoefficients := 0
  468.                 else
  469.                     hnCoefficients := nCoefficients;
  470.                 hfit := fit;
  471.                 for i:=1 to maxCoeff do
  472.                     {hCoeff[i] := Coefficient[i];} {68k-bug}
  473.                     RealToDouble(Coefficient[i], hCoeff[i]);
  474.                 hZeroClip := ZeroClip;
  475.                 hUM := UnitOfMeasure;
  476.                 hBinaryPic := BinaryPic;
  477.                 hSliceStart := SliceStart;
  478.                 hSliceEnd := SliceEnd;
  479.                 if StackInfo <> nil then
  480.                     with StackInfo^ do begin
  481.                             hNSlices := nSlices;
  482.                             hSliceSpacing := SliceSpacing;
  483.                             hFrameInterval := FrameInterval;
  484.                             hCurrentSlice := CurrentSlice;
  485.                             hStackType := StackType;
  486.                         end
  487.                 else begin
  488.                         hNSlices := 0;
  489.                         hSliceSpacing := 0.0;
  490.                         hFrameInterval := 0.0;
  491.                         hCurrentSlice := 0;
  492.                         hStackType := VolumeStack;
  493.                     end;
  494.                 hXUnit := xUnit;
  495.                 ByteCount := SizeOf(TempHdr);
  496.                 if ByteCount <> HeaderSize then begin
  497.                         NumToString(ByteCount, str);
  498.                         PutError('Internal error check: header size is incorrect.');
  499.                         ExitToShell;
  500.                     end;
  501.                 if SavingSelection then begin
  502.                         hnlines := slines;
  503.                         hPixelsPerLine := sPixelsPerLine;
  504.                     end;
  505.                 err := fswrite(f, ByteCount, @TempHdr);
  506.                 SaveHeader := CheckIO(err);
  507.             end; {with}
  508.     end;
  509.  
  510.  
  511.     procedure PackLines;
  512.   {For odd width images, removes the extra bytes at the end of each line required to make RowBytes even.}
  513.         var
  514.             i: integer;
  515.             SrcPtr, DstPtr: ptr;
  516.     begin
  517.         with info^ do begin
  518.                 SrcPtr := ptr(ord4(PicBaseAddr) + BytesPerRow);
  519.                 DstPtr := ptr(ord4(PicBaseAddr) + PixelsPerLine);
  520.                 for i := 1 to nlines - 1 do begin
  521.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  522.                         SrcPtr := ptr(ord4(SrcPtr) + BytesPerRow);
  523.                         DstPtr := ptr(ord4(DstPtr) + PixelsPerLine);
  524.                     end;
  525.             end;
  526.     end;
  527.  
  528.  
  529.     procedure UnpackLines;
  530.   {For odd width images, adds an extra byte to each line so RowBytes is even.}
  531.         var
  532.             i: integer;
  533.             SrcPtr, DstPtr: ptr;
  534.     begin
  535.         with info^ do begin
  536.                 SrcPtr := ptr(ord4(PicBaseAddr) + (nlines - 1) * PixelsPerLine);
  537.                 DstPtr := ptr(ord4(PicBaseAddr) + (nlines - 1) * BytesPerRow);
  538.                 for i := 1 to nlines - 1 do begin
  539.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  540.                         SrcPtr := ptr(ord4(SrcPtr) - PixelsPerLine);
  541.                         DstPtr := ptr(ord4(DstPtr) - BytesPerRow);
  542.                     end;
  543.             end;
  544.     end;
  545.  
  546.  
  547.     function WriteSlices (f: integer): integer;
  548.         var
  549.             ByteCount, SelectionSize: LongInt;
  550.             i, err, SaveCS: integer;
  551.     begin
  552.         with info^, Info^.StackInfo^ do begin
  553.                 SaveCS := CurrentSlice;
  554.                 for i := 1 to nSlices do begin
  555.                         CurrentSlice := i;
  556.                         SelectSlice(CurrentSlice);
  557.                         UpdateTitleBar;
  558.                         ByteCount := ImageSize;
  559.                         if odd(PixelsPerLine) then
  560.                             PackLines;
  561.                         err := fswrite(f, ByteCount, PicBaseAddr);
  562.                         if odd(PixelsPerLine) then
  563.                             UnpackLines;
  564.                         if err <> 0 then
  565.                             leave;
  566.                     end;
  567.                 CurrentSlice := SaveCS;
  568.                 SelectSlice(CurrentSlice);
  569.                 UpdateTitleBar;
  570.                 WriteSlices := err;
  571.             end;
  572.     end;
  573.  
  574.  
  575.     procedure WriteSelection (f: integer; sLines, sPixelsPerLine: LongInt);
  576.   {Contributed by Edward J. Huff(huff@mcclb0.med.nyu.edu).}
  577.         var
  578.             size, offset, ByteCount, BytesDone: LongInt;
  579.             src, dst: ptr;
  580.             err: OSErr;
  581.     begin
  582.         if sPixelsPerLine > UndoBufSize then
  583.             exit(WriteSelection);
  584.         size := sLines * sPixelsPerLine;
  585.         with info^, info^.RoiRect do begin
  586.                 offset := top * BytesPerRow + left;
  587.                 src := ptr(ord4(PicBaseAddr) + offset);
  588.                 BytesDone := 0;
  589.                 while BytesDone < size do begin
  590.                         ByteCount := 0;
  591.                         dst := UndoBuf;
  592.                         while ((ByteCount + sPixelsPerLine) < UndoBufSize) and (BytesDone < size) do begin
  593.                                 BlockMove(src, dst, sPixelsPerLine);
  594.                                 src := ptr(ord4(src) + BytesPerRow);
  595.                                 dst := ptr(ord4(dst) + sPixelsPerLine);
  596.                                 ByteCount := ByteCount + sPixelsPerLine;
  597.                                 BytesDone := BytesDone + sPixelsPerLine;
  598.                             end;
  599.                         err := fswrite(f, ByteCount, UndoBuf);
  600.                     end;
  601.                 SetupUndo; {Needed for drawing roi outline}
  602.             end
  603.     end;
  604.  
  605.  
  606.     procedure SaveRGBTiff(f: integer; SavingSelection: boolean);
  607.     const
  608.         bufsize = 12000;
  609.     var
  610.         i, row, pixel, count, ignore: LongInt;
  611.         vstart, height, hstart, width: LongInt;
  612.         buffer: packed array [0 .. bufsize] of byte;
  613.         rLine, gLine, bLine: LineType;
  614.         err: OSErr;
  615.     begin
  616.         with info^ do begin
  617.             if SavingSelection then with RoiRect do begin
  618.                 vstart := top;
  619.                 height := bottom - top;
  620.                 hstart := left;
  621.                 width := right - left;
  622.             end else begin
  623.                 vstart := 0;
  624.                 height := nLInes;
  625.                 hstart := 0;
  626.                 width := PixelsPerLine;
  627.             end;
  628.             if width > MaxLine then
  629.                 exit(SaveRGBTiff);
  630.             ShowMeter;
  631.             count := 0;
  632.             for row:=0 to height - 1 do begin
  633.                 if (row mod 10) = 0 then
  634.                     UpdateMeter(((row * 100) div height), 'Saving RGB TIFF');
  635.                 SelectSlice(1);
  636.                 GetLine(hstart, vstart + row, width, rLine);
  637.                 SelectSlice(2);
  638.                 GetLine(hstart, vstart + row, width, gLine);
  639.                 SelectSlice(3);
  640.                 GetLine(hstart, vstart + row, width, bLine);
  641.                 for pixel := 0 to width - 1 do begin
  642.                     buffer[count] := 255 - rLine[pixel];
  643.                     buffer[count + 1] := 255 - gLine[pixel];
  644.                     buffer[count + 2] := 255 - bLine[pixel];
  645.                     count := count + 3;
  646.                     if count > (bufsize - 3) then begin
  647.                         if CheckIO(fswrite(f, count, @buffer)) <> noErr then begin
  648.                             exit(SaveRGBTiff);
  649.                             UpdateMeter(-1, '');
  650.                         end;
  651.                         count := 0;
  652.                     end;
  653.                 end; {for}
  654.             end; {for}
  655.             if count > 0 then
  656.                 err := fswrite(f, count, @buffer);
  657.             UpdateMeter(-1, '');
  658.             with StackInfo^ do begin
  659.                 CurrentSlice := 1;
  660.                 SelectSlice(CurrentSlice);
  661.             end;
  662.             UpdateTitleBar;
  663.         end; {with}
  664.     end;
  665.     
  666.  
  667.     function SaveTiffFile (fname: str255; vnum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  668.         var
  669.             f, err, i, width, height: integer;
  670.             HdrSize, ByteCount, ctabSize, StackTiffDirSize, ImageDataSize: LongInt;
  671.             TheInfo: FInfo;
  672.             MCIDHeader: packed array[1..4] of byte;
  673.             SaveColorMap, SaveAs24BitTiff: boolean;
  674.     begin
  675.         SaveTiffFile := false;
  676.         SaveAs24BitTiff := false;
  677.         ShowWatch;
  678.         err := fsopen(fname, vNum, f);
  679.         if CheckIO(err) <> 0 then
  680.             exit(SaveTiffFile);
  681.         with Info^ do begin
  682.                 SaveColorMap := (LutMode <> Grayscale) and (SaveAsWhat <> asRawData);
  683.                 if SaveAsWhat = SaveAsMCID then begin
  684.                         if SavingSelection then begin
  685.                                 width := sPixelsPerLine;
  686.                                 height := slines;
  687.                             end
  688.                         else begin
  689.                                 width := PixelsPerLine;
  690.                                 height := nLines;
  691.                             end;
  692.                         MCIDHeader[1] := (width - 1) mod 256;
  693.                         MCIDHeader[2] := (width - 1) div 256;
  694.                         MCIDHeader[3] := (height - 1) mod 256;
  695.                         MCIDHeader[4] := (height - 1) div 256;
  696.                         ByteCount := 4;
  697.                         err := fswrite(f, ByteCount, @MCIDHeader);
  698.                     end;
  699.                 HeaderOffset := TiffDirSize;
  700.                 ImageDataOffset := TiffDirSize + HeaderSize;
  701.                 if SaveColorMap then
  702.                     ctabSize := SizeOf(TiffColorMapType)
  703.                 else
  704.                     ctabSize := 0;
  705.                 StackTiffDirSize := 0;
  706.                 if SavingSelection then
  707.                     ImageDataSize := ord4(sLines) * sPixelsPerLine
  708.                 else
  709.                     ImageDataSize := ImageSize;
  710.                 if StackInfo <> nil then begin
  711.                         ImageDataSize := ImageSize * StackInfo^.nSlices;
  712.                         if SaveAsWhat <> asRawData then
  713.                             StackTiffDirSize := SizeOf(StackIFDType) * (StackInfo^.nSlices - 1);
  714.                         if (StackInfo^.StackType = rgbStack) and (StackInfo^.nSlices = 3) then begin
  715.                             SaveAs24BitTiff := true;
  716.                             ctabSize := 0;
  717.                             StackTiffDirSize := 0;
  718.                         end;
  719.                     end;
  720.                 if (SaveAsWhat <> asRawData) and (SaveAsWhat <> SaveAsMCID) then begin
  721.                         if SaveTiffDir(f, slines, sPixelsPerLine, SavingSelection, ctabSize, ImageDataSize) <> NoErr then begin
  722.                                 err := fsclose(f);
  723.                                 err := FSDelete(fname, vnum);
  724.                                 exit(SaveTiffFile)
  725.                             end;
  726.                         err := SetFPos(f, FSFromStart, TiffDirSize);
  727.                         if SaveHeader(f, slines, sPixelsPerLine, vnum, fname, SavingSelection, true) <> NoErr then begin
  728.                                 err := fsclose(f);
  729.                                 err := FSDelete(fname, vnum);
  730.                                 exit(SaveTiffFile)
  731.                             end;
  732.                     end;
  733.                 if SaveAsWhat = SaveAsMCID then
  734.                     KillRoi;
  735.                 if SaveAs24bitTiff then
  736.                     SaveRGBTiff(f, SavingSelection)
  737.                 else if SavingSelection then
  738.                     WriteSelection(f, sLines, sPixelsPerLine)
  739.                 else if StackInfo <> nil then
  740.                     err := WriteSlices(f)
  741.                 else begin
  742.                         ByteCount := ImageDataSize;
  743.                         if odd(PixelsPerLine) then
  744.                             PackLines;
  745.                         err := fswrite(f, ByteCount, PicBaseAddr);
  746.                         if odd(PixelsPerLine) then
  747.                             UnpackLines;
  748.                     end;
  749.                 if SaveAsWhat = SaveAsMCID then
  750.                     InvertPic;
  751.                 if CheckIO(err) <> 0 then begin
  752.                         err := fsclose(f);
  753.                         err := FSDelete(fname, vnum);
  754.                         exit(SaveTiffFile)
  755.                     end;
  756.                 if SaveAsWhat = asRawData then
  757.                     HdrSize := 0
  758.                 else if SaveAsWhat = SaveAsMCID then begin
  759.                         HdrSize := 4;
  760.                         SaveAsWhat := asRawData;
  761.                     end
  762.                 else
  763.                     HdrSize := HeaderSize + TiffDirSize;
  764.                 if SaveColorMap then
  765.                     SaveTiffColorMap(f, ImageDataSize);
  766.                 if StackTiffDirSize > 0 then
  767.                     err := WriteExtraTiffIFDs(f, ImageDataSize, cTabSize);
  768.                 err := SetEOF(f, HdrSize + ImageDataSize + ctabSize + StackTiffDirSize);
  769.                 err := fsclose(f);
  770.                 err := GetFInfo(fname, vnum, TheInfo);
  771.                 if TheInfo.fdCreator <> 'Imag' then begin
  772.                         TheInfo.fdCreator := 'Imag';
  773.                         err := SetFInfo(fname, vnum, TheInfo);
  774.                     end;
  775.                 if SaveAsWhat = asRawData then begin
  776.                         TheInfo.fdType := 'RawD';
  777.                         err := SetFInfo(fname, vnum, TheInfo);
  778.                     end
  779.                 else if TheInfo.fdType <> 'TIFF' then begin
  780.                         TheInfo.fdType := 'TIFF';
  781.                         err := SetFInfo(fname, vnum, TheInfo);
  782.                     end;
  783.                 err := FlushVol(nil, vNum);
  784.                 if not SavingSelection then begin
  785.                         if (PictureType <> BlankField) and (PictureType <> FrameGrabberType)  and (SaveAsWhat <> asRawData) then begin
  786.                                 PictureType := TiffFile;
  787.                                 RemovePath(fname);
  788.                                 TruncateString(fname, maxTitle);
  789.                                 title := fname;
  790.                                 vref := vnum;
  791.                                 UpdateTitleBar;
  792.                                 if StackInfo = nil then begin
  793.                                         revertable := true;
  794.                                         InvertedImage := false;
  795.                                     end;
  796.                             end;
  797.                     end;
  798.                 if (SaveAsWhat <> asRawData) and (not RoiShowing) then
  799.                     Changes := false;
  800.             end; {with}
  801.         SaveTiffFile := true;
  802.     end;
  803.  
  804.  
  805.     procedure SaveAsTIFF (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean);
  806.         var
  807.             err: integer;
  808.             TheInfo: FInfo;
  809.             replacing, ok: boolean;
  810.             name: str255;
  811.     begin
  812.         if info = NoInfo then
  813.             exit(SaveAsTIFF);
  814.         err := GetFInfo(fname, RefNum, TheInfo);
  815.         case err of
  816.             NoErr: 
  817.                 with TheInfo do begin
  818.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') and (fdType <> 'RawD') and (fdType <> 'PICS') then begin
  819.                                 TypeMismatch(fname);
  820.                                 exit(SaveAsTIFF)
  821.                             end;
  822.                         replacing := true;
  823.                     end;
  824.             FNFerr:  begin
  825.                     if SaveAsWhat = asRawData then
  826.                         err := create(fname, RefNum, 'Imag', 'RawD')
  827.                     else
  828.                         err := create(fname, RefNum, 'Imag', 'TIFF');
  829.                     if CheckIO(err) <> 0 then
  830.                         exit(SaveAsTIFF);
  831.                     replacing := false;
  832.                 end;
  833.             otherwise
  834.                 if CheckIO(err) <> 0 then
  835.                     exit(SaveAsTIFF);
  836.         end;
  837.         if replacing then
  838.             if not RoomForFile(fname, RefNum, slines, sPixelsPerLine, SavingSelection) then
  839.                 exit(SaveAsTIFF);
  840.         ok := SaveTiffFile(fname, RefNum, slines, sPixelsPerLine, SavingSelection);
  841.         if ok then
  842.             UpdateWindowsMenuItem;
  843.         with info^ do
  844.             if SavingSelection and Replacing and (PictureType <> BlankField) and (PictureType <> FrameGrabberType)  then
  845.                 PictureType := Leftover;
  846.     end;
  847.  
  848.  
  849.     function SavePICTFile (fname: str255; vnum: integer; SavingSelection, NewFile: boolean): boolean;
  850.         var
  851.             f, err, i, v: integer;
  852.             ByteCount, PICTSize: LongInt;
  853.             PicH: PicHandle;
  854.             fRect, frect2: rect;
  855.             tPort: GrafPtr;
  856.             TheInfo: FInfo;
  857.             SaveInfoRec: PicInfo;
  858.             HeaderSaved: boolean;
  859.             SaveGDevice: GDHandle;
  860.  
  861.         procedure Abort;
  862.         begin
  863.             err := fsclose(f);
  864.             if NewFile then
  865.                 err := FSDelete(fname, vnum);
  866.             DisposeHandle(handle(PicH));
  867.             {exit(SavePICTFile)}   {ppc-bug}
  868.         end;
  869.  
  870.     begin
  871.         with info^ do begin
  872.                 if OpPending then
  873.                     KillRoi;
  874.                 SavePICTFile := false;
  875.                 ShowWatch;
  876.                 GetPort(tPort);
  877.                 if SavingSelection then
  878.                     fRect := RoiRect
  879.                 else
  880.                     SetRect(fRect, 0, 0, PixelsPerLine, nlines);
  881.                 with frect do
  882.                     SetRect(frect2, 0, 0, right - left, bottom - top);
  883.                 with osPort^ do begin
  884.                         SaveGDevice := GetGDevice;
  885.                         SetGDevice(osGDevice);
  886.                         SetPort(GrafPtr(osPort));
  887.                         pmForeColor(BlackIndex);
  888.                         pmBackColor(WhiteIndex);
  889.                         if OldSystem then begin
  890.                                 RGBForeColor(BlackRGB);
  891.                                 RGBBackColor(WhiteRGB);
  892.                             end;
  893.                         ClipRect(PicRect);
  894.                         LoadLUT(cTable);
  895.                         PicH := OpenPicture(fRect2);
  896.                         CopyBits(BitMapHandle(PortPixMap)^^, BitMapHandle(PortPixMap)^^, frect, frect2, SrcCopy, nil);
  897.                         ClosePicture;
  898.                         pmForeColor(ForegroundIndex);
  899.                         pmBackColor(BackgroundIndex);
  900.                     end;
  901.                 SetPort(tPort);
  902.                 SetGDevice(SaveGDevice);
  903.                 PICTSize := GetHandleSize(handle(PicH));
  904.                 if PICTSize <= 10 then begin
  905.                         PutError('Sorry, but there is not enough memory available to save this PICT file. Try closing some windows, or save as TIFF.');
  906.                         if NewFile then
  907.                             err := FSDelete(fname, vnum);
  908.                         DisposeHandle(handle(PicH));
  909.                         exit(SavePICTFile)
  910.                     end;
  911.                 err := fsopen(fname, vnum, f);
  912.                 err := SetFPos(f, FSFromStart, 0);
  913.                 SaveInfoRec := Info^;
  914.                 if (LutMode = GrayScale) or (LutMode = CustomGrayScale) then begin
  915.                         nColors := 256;
  916.                         ColorStart := 0;
  917.                         ColorEnd := 255;
  918.                         LUTMode := Grayscale;
  919.                         IdentityFunction := true;
  920.                     end;
  921.                 HeaderSaved := SaveHeader(f, 0, 0, vnum, fname, SavingSelection, false) = 0;
  922.                 Info^ := SaveInfoRec;
  923.                 if not HeaderSaved then begin
  924.                     abort;
  925.                     exit(SavePICTFile)
  926.                 end;
  927.                 err := fswrite(f, PICTSize, pointer(PicH^));
  928.                 if CheckIO(err) <> 0 then begin
  929.                     abort; 
  930.                     exit(SavePICTFile)
  931.                 end;
  932.                 DisposeHandle(handle(PicH));
  933.                 ByteCount := PICTSize + HeaderSize;
  934.                 err := SetEOF(f, ByteCount);
  935.                 err := fsclose(f);
  936.                 err := GetFInfo(fname, vnum, TheInfo);
  937.                 if TheInfo.fdCreator <> 'Imag' then begin
  938.                         TheInfo.fdCreator := 'Imag';
  939.                         err := SetFInfo(fname, vnum, TheInfo);
  940.                     end;
  941.                 if TheInfo.fdType <> 'PICT' then begin
  942.                         TheInfo.fdType := 'PICT';
  943.                         err := SetFInfo(fname, vnum, TheInfo);
  944.                     end;
  945.                 err := FlushVol(nil, vnum);
  946.                 if not SavingSelection then begin
  947.                         if (PictureType <> BlankField) and (PictureType <> FrameGrabberType)  and (PictureType <> NullPicture) then begin
  948.                                 PictureType := PictFile;
  949.                                 RemovePath(fname);
  950.                                 TruncateString(fname, maxTitle);
  951.                                 title := fname;
  952.                                 UpdateTitleBar;
  953.                                 vref := vnum;
  954.                                 revertable := true;
  955.                                 InvertedImage := false;
  956.                             end;
  957.                         Changes := false;
  958.                     end;
  959.             end; {with}
  960.         SavePICTFile := true;
  961.     end;
  962.  
  963.  
  964.     procedure SaveAsPICT (fname: str255; RefNum: integer; SavingSelection: boolean);
  965.         var
  966.             f, err, i: integer;
  967.             where: Point;
  968.             TheInfo: FInfo;
  969.             replacing, ok: boolean;
  970.             name: str255;
  971.     begin
  972.         err := GetFInfo(fname, RefNum, TheInfo);
  973.         case err of
  974.             NoErr: 
  975.                 with TheInfo do begin
  976.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') then begin
  977.                                 TypeMismatch(fname);
  978.                                 exit(SaveAsPICT)
  979.                             end;
  980.                         replacing := true;
  981.                     end;
  982.             FNFerr:  begin
  983.                     err := create(fname, RefNum, 'Imag', 'PICT');
  984.                     if CheckIO(err) <> 0 then
  985.                         exit(SaveAsPICT);
  986.                     replacing := false;
  987.                 end;
  988.             otherwise
  989.                 if CheckIO(err) <> 0 then
  990.                     exit(SaveAsPICT);
  991.         end;
  992.         ok := SavePICTFile(fname, RefNum, SavingSelection, not Replacing);
  993.         if ok then
  994.             UpdateWindowsMenuItem;
  995.         with info^ do
  996.             if SavingSelection and replacing and (PictureType <> BlankField) and (PictureType <> FrameGrabberType)  then
  997.                 PictureType := Leftover;
  998.     end;
  999.  
  1000.  
  1001.     procedure SaveSelection (fname: str255; RefNum: integer; SaveAsSameType: boolean);
  1002.         var
  1003.             slines, spixelsPerLine: integer;
  1004.     begin
  1005.         if info = NoInfo then
  1006.             exit(SaveSelection);
  1007.         if NoSelection or NotRectangular or NotInBounds then
  1008.             exit(SaveSelection);
  1009.         if OpPending then
  1010.             KillRoi;
  1011.         with info^ do begin
  1012.                 with RoiRect do begin
  1013.                         sPixelsPerLine := right - left;
  1014.                         slines := bottom - top;
  1015.                     end;
  1016.                 if (PictureType = PictFile) and SaveAsSameType and (SaveAsWhat <> asRawData) then
  1017.                     SaveAsPICT(fname, RefNum, true)
  1018.                 else
  1019.                     SaveAsTIFF(fname, RefNum, sLines, sPixelsPerLine, true);
  1020.             end;
  1021.     end;
  1022.  
  1023.  
  1024.     procedure SaveAsText (fname: str255; RefNum: integer);
  1025.         var
  1026.             err, f: integer;
  1027.             TheInfo: FInfo;
  1028.             ByteCount: LongInt;
  1029.     begin
  1030.         err := GetFInfo(fname, RefNum, TheInfo);
  1031.         case err of
  1032.             NoErr: 
  1033.                 if TheInfo.fdType <> 'TEXT' then begin
  1034.                         TypeMismatch(fname);
  1035.                         exit(SaveAsText)
  1036.                     end;
  1037.             FNFerr:  begin
  1038.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1039.                     if CheckIO(err) <> 0 then
  1040.                         exit(SaveAsText);
  1041.                 end;
  1042.             otherwise
  1043.                 if CheckIO(err) <> 0 then
  1044.                     exit(SaveAsTExt)
  1045.         end;
  1046.         ShowWatch;
  1047.         err := fsopen(fname, RefNum, f);
  1048.         if CheckIO(err) <> 0 then
  1049.             exit(SaveAsText);
  1050.         ByteCount := TextBufSize;
  1051.         err := fswrite(f, ByteCount, ptr(TextBufP));
  1052.         if CheckIO(err) <> 0 then
  1053.             exit(SaveAsText);
  1054.         err := SetEof(f, ByteCount);
  1055.         err := fsclose(f);
  1056.         err := FlushVol(nil, RefNum);
  1057.         if WhatsOnClip = TextOnClip then
  1058.             WhatsOnClip := NothingOnClip;
  1059.     end;
  1060.  
  1061.  
  1062.     procedure SaveAsPICS (fname: str255; fRefNum: integer);
  1063.         const
  1064.             rErr = 'Error Saving PICS file.';
  1065.         var
  1066.             err: OSErr;
  1067.             TheInfo: FInfo;
  1068.             replacing: boolean;
  1069.             rRefNum, i, SaveCS: integer;
  1070.             frect: rect;
  1071.             PicH: array[1..MaxSlices] of PicHandle;
  1072.             MinFreeRequired: LongInt;
  1073.             SaveGDevice: GDHandle;
  1074.     begin
  1075.         with info^, Info^.StackInfo^ do begin
  1076.                 if StackInfo = nil then begin
  1077.                         PutError('Only Stacks can be saved in PICS format.');
  1078.                         SaveAsWhat := asTiff;
  1079.                         exit(SaveAsPICS);
  1080.                     end;
  1081.                 if ImageSize > MinFree then
  1082.                     MinFreeRequired := ImageSize
  1083.                 else
  1084.                     MinFreeRequired := MinFree;
  1085.                 if MaxBlock < MinFreeRequired then begin
  1086.                         PutError('Not enough memory available to save in PICS format.');
  1087.                         exit(SaveAsPICS);
  1088.                     end;
  1089.                 err := GetFInfo(fname, fRefNum, TheInfo);
  1090.                 if err = NoErr then
  1091.                     with TheInfo do begin
  1092.                             if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'PICS') then begin
  1093.                                     TypeMismatch(fname);
  1094.                                     exit(SaveAsPICS)
  1095.                                 end;
  1096.                             err := FSDelete(fname, fRefNum);
  1097.                         end;
  1098.                 ShowWatch;
  1099.                 err := SetVol(nil, fRefNum);
  1100.                 CreateResFile(fname);
  1101.                 if ResError <> NoErr then
  1102.                     exit(SaveAsPICS);
  1103.                 rRefNum := OpenResFile(fname);
  1104.                 SaveCS := CurrentSlice;
  1105.                 SaveGDevice := GetGDevice;
  1106.                 SetGDevice(osGDevice);
  1107.                 SetPort(GrafPtr(osPort));
  1108.                 with PicRect do
  1109.                     SetRect(frect, 0, 0, right - left, bottom - top);
  1110.                 ClipRect(frect);
  1111.                 LoadLUT(ctable);
  1112.                 pmForeColor(BlackIndex);
  1113.                 pmBackColor(WhiteIndex);
  1114.                 if OldSystem then begin
  1115.                         RGBForeColor(BlackRGB);
  1116.                         RGBBackColor(WhiteRGB);
  1117.                     end;
  1118.                 for i := 1 to nSlices do begin
  1119.                         CurrentSlice := i;
  1120.                         SelectSlice(CurrentSlice);
  1121.                         UpdateTitleBar;
  1122.                         PicH[i] := OpenPicture(frect);
  1123.                         with osPort^ do
  1124.                             CopyBits(BitMapHandle(portPixMap)^^, BitMapHandle(portPixMap)^^, PicRect, frect, SrcCopy, nil);
  1125.                         ClosePicture;
  1126.                         if (PicH[i] = nil) or ((PicH[i] <> nil) and (GetHandleSize(handle(PicH[i])) <= 10)) then begin
  1127.                                 PutError(rErr);
  1128.                                 leave;
  1129.                             end;
  1130.                         AddResource(handle(PicH[i]), 'PICT', i - 1 + 128, '');
  1131.                         if ResError <> NoErr then begin
  1132.                                 PutError(rErr);
  1133.                                 leave;
  1134.                             end;
  1135.                         WriteResource(handle(PicH[i]));
  1136.                         ReleaseResource(handle(PicH[i]));
  1137.                         if ResError <> NoErr then begin
  1138.                                 PutError(rErr);
  1139.                                 leave;
  1140.                             end;
  1141.                     end; {for}
  1142.                 pmForeColor(ForegroundIndex);
  1143.                 pmBackColor(BackgroundIndex);
  1144.                 SetGDevice(SaveGDevice);
  1145.                 CurrentSlice := SaveCS;
  1146.                 SelectSlice(CurrentSlice);
  1147.                 RemovePath(fname);
  1148.                 TruncateString(fname, maxTitle);
  1149.                 title := fname;
  1150.                 PictureType := PicsFile;
  1151.                 UpdateTitleBar;
  1152.                 CloseResFile(rRefNum);
  1153.                 if ResError = NoErr then
  1154.                     changes := false
  1155.                 else
  1156.                     PutError(rErr);
  1157.                 err := GetFInfo(fname, fRefNum, TheInfo);
  1158.                 TheInfo.fdType := 'PICS';
  1159.                 TheInfo.fdCreator := 'Imag';
  1160.                 err := SetFInfo(fname, fRefNum, TheInfo);
  1161.                 err := FlushVol(nil, fRefNum);
  1162.                 UpdateWindowsMenuItem;
  1163.             end; {with}
  1164.     end;
  1165.  
  1166.  
  1167.     function SuggestedName: str255;
  1168.         var
  1169.             name: str255;
  1170.     begin
  1171.         case SaveAsWhat of
  1172.             asTiff, asPict, asMacPaint, asRawData, asPICS:  begin
  1173.                     name := info^.title;
  1174.                     if name = 'Camera' then
  1175.                         name := 'Untitled';
  1176.                     SuggestedName := name;
  1177.                 end;
  1178.             AsPalette: 
  1179.                 SuggestedName := 'Palette';
  1180.             AsOutline: 
  1181.                 SuggestedName := 'Outline';
  1182.         end;
  1183.     end;
  1184.  
  1185.  
  1186.     function SaveAsHook (item: integer; theDialog: DialogPtr): integer;
  1187.         const
  1188.             EditTextID = 7;
  1189.             TiffID = 9;
  1190.             OutlineID = 14;
  1191.         var
  1192.             i: integer;
  1193.             fname: str255;
  1194.             NameEdited: boolean;
  1195.     begin
  1196.         if item = -1 then {Initialize}
  1197.             SetDlogItem(theDialog, TiffID + ord(SaveAsWhat), 1);
  1198.         fname := GetDString(theDialog, EditTextID);
  1199.         NameEdited := fname <> SuggestedName;
  1200.         if (item >= TiffID) and (item <= OutlineID) then begin
  1201.                 SaveAsWhat := SaveAsWhatType(item - TiffID);
  1202.                 if not NameEdited then begin
  1203.                         SetDString(theDialog, EditTextID, SuggestedName);
  1204.                         SelectdialogItemText(theDialog, EditTextID, 0, 32767);
  1205.                     end;
  1206.                 for i := TiffID to OutlineID do
  1207.                     SetDlogItem(theDialog, i, 0);
  1208.                 SetDlogItem(theDialog, item, 1);
  1209.             end;
  1210.         SaveAsHook := item;
  1211.     end;
  1212.  
  1213.  
  1214.     procedure SaveAs (name: str255; RefNum: integer);
  1215.         const
  1216.             CustomDialogID = 60;
  1217.         var
  1218.             where: Point;
  1219.             reply: SFReply;
  1220.             isSelection: boolean;
  1221.             kind: integer;
  1222.     begin
  1223.         if SaveAsDHookProc=nil
  1224.             then SaveAsDHookProc:=NewRoutineDescriptor(@SaveAsHook, uppDlgHookProcInfo, GetCurrentISA);
  1225.         with info^ do begin
  1226.                 if SaveAllState = SaveAllStage2 then begin
  1227.                         name := title;
  1228.                         RefNum := SaveRefNum;
  1229.                         if SaveAsWhat = AsPalette then
  1230.                             SaveAsWhat := AsTiff;
  1231.                     end
  1232.                 else if (name = '') or ((RefNum = 0) and (pos(':', name) = 0)) then begin
  1233.                         where.v := 50;
  1234.                         where.h := 50;
  1235.                         if (StackInfo = nil) and (SaveAsWhat = asPICS) then
  1236.                             SaveAsWhat := asTIFF;
  1237.                         if (StackInfo <> nil) and ((SaveAsWhat = asPICT) or (SaveAsWhat = asMacPaint)) then
  1238.                             SaveAsWhat := asTIFF;
  1239.                         if name = '' then
  1240.                             name := SuggestedName;
  1241.                         SFPPutFile(Where, 'Save as?', name, SaveAsDHookProc, reply, CustomDialogID, nil);
  1242.                         if not reply.good then begin
  1243.                                 SaveAllState := NoSaveAll;
  1244.                                 AbortMacro;
  1245.                                 exit(SaveAs);
  1246.                             end;
  1247.                         with reply do begin
  1248.                                 name := fname;
  1249.                                 RefNum := vRefNum;
  1250.                                 DefaultRefNum := RefNum;
  1251.                             end;
  1252.                     end;
  1253.                 if StackInfo <> nil then begin
  1254.                         if (SaveAsWhat <> asOutline) and not ((StackInfo^.StackType = RGBStack) and (StackInfo^.nSlices = 3)) then
  1255.                             KillRoi;
  1256.                         SaveAllState := NoSaveAll;
  1257.                         if not ((SaveAsWhat = asTIFF) or (SaveAsWhat = asPICS) or (SaveAsWhat = asPalette) or (SaveAsWhat = asOutline)) then begin
  1258.                                 PutError('Stacks can only be saved in TIFF or PICS format.');
  1259.                                 SaveAsWhat := asTIFF;
  1260.                                 exit(SaveAs);
  1261.                             end;
  1262.                     end;
  1263.                 isSelection := RoiShowing and (RoiType = RectRoi);
  1264.                 if SaveAllState = SaveAllStage1 then begin
  1265.                         SaveRefNum := RefNum;
  1266.                         SaveAllState := SaveAllStage2;
  1267.                     end;
  1268.                 case SaveAsWhat of
  1269.                     asTiff, asRawData: 
  1270.                         if isSelection then
  1271.                             SaveSelection(name, RefNum, false)
  1272.                         else
  1273.                             SaveAsTIFF(name, RefNum, 0, 0, false);
  1274.                     asPict: 
  1275.                         if isSelection then
  1276.                             SaveAsPICT(name, RefNum, true)
  1277.                         else
  1278.                             SaveAsPICT(name, RefNum, false);
  1279.                     asMacPaint: 
  1280.                         SaveAsMacPaint(name, RefNum);
  1281.                     asPICS: 
  1282.                         SaveAsPICS(name, RefNum);
  1283.                     AsPalette: 
  1284.                         SaveColorTable(name, RefNum);
  1285.                     AsOutline: 
  1286.                         SaveOutline(name, RefNum);
  1287.                 end; {case}
  1288.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  1289.                     SaveAsWhat := asTIFF;
  1290.             end; {with}
  1291.     end;
  1292.  
  1293.  
  1294.     procedure SaveFile;
  1295.         var
  1296.             fname: str255;
  1297.             size: LongInt;
  1298.             ok: boolean;
  1299.     begin
  1300.         if CurrentWindow = ResultsKind then begin
  1301.                 Export('', 0);
  1302.                 exit(SaveFile);
  1303.             end;
  1304.         if CurrentWindow = TextKind then begin
  1305.                 SaveText;
  1306.                 exit(SaveFile);
  1307.             end;
  1308.         if OpPending then
  1309.             KillRoi;
  1310.         with Info^ do begin
  1311.                 fname := title;
  1312.                 size := 0;
  1313.                 if PictureType = TiffFile then
  1314.                     ok := SaveTiffFile(fname, vref, 0, 0, false)
  1315.                 else if PictureType = PictFile then
  1316.                     ok := SavePICTFile(fname, vref, false, false)
  1317.                 else
  1318.                     SaveAs('', 0);
  1319.             end;
  1320.     end;
  1321.  
  1322.  
  1323.     function SaveChanges: integer;
  1324.         const
  1325.             yesID = 1;
  1326.             noID = 2;
  1327.             cancelID = 3;
  1328.         var
  1329.             id: integer;
  1330.             reply: SFReply;
  1331.     begin
  1332.         id := 0;
  1333.         if info^.changes then
  1334.             with info^ do begin
  1335.                     if CommandPeriod or MakingStack or (macro and ((MacroCommand = DisposeC) or (MacroCommand = DisposeAllC))) then begin
  1336.                             SaveChanges := ok;
  1337.                             exit(SaveChanges);
  1338.                         end;
  1339.                     ParamText(title, '', '', '');
  1340.                     InitCursor;
  1341.                     id := alert(600, nil);
  1342.                     if id = yesID then begin
  1343.                             SaveFile;
  1344.                             InitCursor;
  1345.                         end; {if yes}
  1346.                 end; {if changes}
  1347.         if (id = cancelID) or ((id = yesID) and (info^.changes)) then
  1348.             SaveChanges := cancel
  1349.         else
  1350.             SaveChanges := ok;
  1351.     end;
  1352.  
  1353.  
  1354.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  1355.         var
  1356.             i, kind, n: integer;
  1357.             TempInfo: InfoPtr;
  1358.             TempTextInfo: TextInfoPtr;
  1359.             SizeStr, str: str255;
  1360.             wp: ^WindowPtr;
  1361.             pcrect: rect;
  1362.     begin
  1363.         if WhichWindow = nil then
  1364.             exit(CloseAWindow);
  1365.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1366.         CloseAWindow := ok;
  1367.         if WhichWindow = VideoControl then begin
  1368.                 DisposeDialog(VideoControl);
  1369.                 VideoControl := nil;
  1370.                 exit(CloseAWindow);
  1371.             end;
  1372.         case kind of
  1373.             PicKind:  begin
  1374.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1375.                     with Info^ do begin
  1376.                             if PicNum = 0 then begin
  1377.                                     beep;
  1378.                                     exit(CloseAWindow);
  1379.                                 end;
  1380.                             if SaveChanges = cancel then begin
  1381.                                     CloseAWindow := cancel;
  1382.                                     exit(CloseAWindow)
  1383.                                 end;
  1384.                             DeleteMenuItem(WindowsMenuH, PicNum + WindowsMenuItems + nTextWindows);
  1385.                             for i := PicNum to nPics - 1 do begin
  1386.                                     PicWindow[i] := PicWindow[i + 1];
  1387.                                     TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  1388.                                     TempInfo^.PicNum := i
  1389.                                 end;
  1390.                             if PictureType = BlankField then
  1391.                                 BlankFieldInfo := nil;
  1392.                             if (PictureType = FrameGrabberType) and (FrameGrabber = QTvdig) then
  1393.                                 CloseVdig;
  1394.                             if StackInfo <> nil then begin
  1395.                                     with StackInfo^ do
  1396.                                         for i := 1 to nSlices do
  1397.                                             DisposeHandle(PicBaseH[i]);
  1398.                                     DisposePtr(pointer(StackInfo));
  1399.                                 end
  1400.                             else begin
  1401.                                     if not MakingStack then
  1402.                                         DisposeHandle(PicBaseHandle);
  1403.                                 end;
  1404.                             DisposeWindow(WhichWindow);
  1405.                             CloseCPort(osPort);
  1406.                             DisposePtr(ptr(osPort));
  1407.                             DisposeRgn(roiRgn);
  1408.                             if DataH <> nil then
  1409.                                     DisposeHandle(DataH);
  1410.                             nPics := nPics - 1;
  1411.                             OpPending := false;
  1412.                             isInsertionPoint := false;
  1413.                             DisposePtr(pointer(Info));
  1414.                             Info := NoInfo;
  1415.                             if (nPics = 0) and (not finished) then
  1416.                                 with info^ do begin
  1417.                                         LoadLUT(info^.cTable);
  1418.                                         if (LutMode = GrayScale) or (LutMode = CustomGrayScale) then
  1419.                                             DrawMap;
  1420.                                     end;
  1421.                             PicLeft := PicLeftBase;
  1422.                             PicTop := PicTopBase;
  1423.                         end;
  1424.                 end; {PicKind}
  1425.             HistoKind:  begin
  1426.                     DisposeWindow(HistoWindow);
  1427.                     HistoWindow := nil;
  1428.                     ContinuousHistogram := false;
  1429.                 end;
  1430.             ProfilePlotKind, CalibrationPlotKind:  begin
  1431.                     DisposeWindow(PlotWindow);
  1432.                     PlotWindow := nil;
  1433.                     KillPicture(PlotPICT);
  1434.                     PlotPICT := nil;
  1435.                 end;
  1436.             ResultsKind:  begin
  1437.                     DisposeWindow(ResultsWindow);
  1438.                     ResultsWindow := nil;
  1439.                     TEDispose(ListTE);
  1440.                 end;
  1441.             TextKind:  begin
  1442.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  1443.                     if TextInfo <> nil then
  1444.                         with TextInfo^ do begin
  1445.                                 if SaveTextChanges = cancel then begin
  1446.                                         CloseAWindow := cancel;
  1447.                                         exit(CloseAWindow)
  1448.                                     end;
  1449.                                 DisposeWindow(TextWindowPtr);
  1450.                                 DeleteMenuItem(WindowsMenuH, WindowsMenuItems - 1 + WindowNum);
  1451.                                 TEDispose(TextTE);
  1452.                                 DisposePtr(ptr(TextInfo));
  1453.                                 TextInfo := nil;
  1454.                                 for i := WindowNum to nTextWindows - 1 do begin
  1455.                                         TextWindow[i] := TextWindow[i + 1];
  1456.                                         TempTextInfo := pointer(WindowPeek(TextWindow[i])^.RefCon);
  1457.                                         TempTextInfo^.WindowNum := i
  1458.                                     end;
  1459.                                 nTextWindows := nTextWindows - 1;
  1460.                             end;
  1461.                 end;
  1462.             PasteControlKind:  begin
  1463.                     GetWindowRect(PasteControl, pcrect);
  1464.                     with pcrect do begin
  1465.                             PasteControlLeft := left;
  1466.                             PasteControlTop := top;
  1467.                         end;
  1468.                     DisposeWindow(PasteControl);
  1469.                     PasteControl := nil;
  1470.                     wp := pointer(GhostWindow);
  1471.                     wp^ := nil;
  1472.                 end;
  1473.             otherwise
  1474.                 ;
  1475.         end; {case}
  1476.     end;
  1477.  
  1478.  
  1479.     procedure DoClose;
  1480.         var
  1481.             ignore: integer;
  1482.             fwptr: WindowPtr;
  1483.             kind: integer;
  1484.     begin
  1485.         fwptr := FrontWindow;
  1486.         if fwptr <> nil then begin
  1487.                 if fwptr = VideoControl then begin
  1488.                         DisposeDialog(VideoControl);
  1489.                         VideoControl := nil;
  1490.                         exit(DoClose);
  1491.                     end;
  1492.                 kind := WindowPeek(fwptr)^.WindowKind;
  1493.                 if (kind = PicKind) or (kind = ProfilePlotKind) or (kind = CalibrationPlotKind) or (kind = HistoKind) or (Kind = PasteControlKind) or (Kind = ResultsKind) or (Kind = TextKind) then
  1494.                     ignore := CloseAWindow(fwptr);
  1495.             end;
  1496.     end;
  1497.  
  1498.  
  1499.     procedure Read4BitTIFF (f: integer);
  1500.         var
  1501.             vloc, hloc, i: integer;
  1502.             ByteCount, count: LongInt;
  1503.             err: OSErr;
  1504.             UnpackedLine, PackedLine: LineType;
  1505.     begin
  1506.         with info^ do begin
  1507.                 if PixelsPerLine > MaxLine then
  1508.                     exit(Read4BitTIFF);
  1509.                 ByteCount := (PixelsPerLine + 1) div 2;
  1510.                 for vloc := 0 to nLines - 1 do begin
  1511.                         err := FSRead(f, ByteCount, @PackedLine);
  1512.                         i := 0;
  1513.                         for hloc := 0 to PixelsPerLine - 1 do
  1514.                             if odd(hloc) then begin
  1515.                                     UnpackedLine[hloc] := bsl(band(PackedLine[i], $F), 4);
  1516.                                     i := i + 1;
  1517.                                 end
  1518.                             else
  1519.                                 UnpackedLine[hloc] := band(PackedLine[i], $F0);
  1520.                         PutLine(0, vloc, PixelsPerLine, UnpackedLine);
  1521.                     end;
  1522.             end; {with}
  1523.     end;
  1524.  
  1525.  
  1526. {$POP}
  1527.  
  1528.     procedure CheckFileSize(f:integer; var size: LongInt; offset: LongInt);
  1529.     {Check to make sure we don't read past the end of file.}
  1530.     var
  1531.         FileSize: LongInt;
  1532.         err: OSErr;
  1533.     begin
  1534.         err := GetEof(f, FileSize);
  1535.         if (offset + size) > FileSize then begin
  1536.            size := FileSize - offset;
  1537.            if size < 0 then size := 0;
  1538.         end;
  1539.     end;
  1540.  
  1541.  
  1542.     procedure ReadStackSlices (f, nExtraImages: integer; var table: TiffIFDTable);
  1543.         var
  1544.             i, err, SaveCS: integer;
  1545.             h: handle;
  1546.             DataSize: LongInt;
  1547.             PartialStack: boolean;
  1548.     begin
  1549.         ShowMessage(CmdPeriodToStop);
  1550.         PartialStack := false;
  1551.         with info^ do begin
  1552.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  1553.                 if StackInfo = nil then
  1554.                     exit(ReadStackSlices);
  1555.             end;
  1556.         with info^, info^.StackInfo^ do begin
  1557.                 nSlices := nExtraImages + 1;
  1558.                 CurrentSlice := TempStackInfo.CurrentSlice;
  1559.                 if (CurrentSlice < 1) or (CurrentSlice > nSlices) then
  1560.                     CurrentSlice := 1;
  1561.                 SliceSpacing := TempStackInfo.SliceSpacing;
  1562.                 FrameInterval := TempStackInfo.FrameInterval;
  1563.                 StackType := TempStackInfo.StackType;
  1564.                 SaveCS := CurrentSlice;
  1565.                 PicBaseH[1] := PicBaseHandle;
  1566.                 revertable := false;
  1567.                 for i := 2 to nSlices do begin
  1568.                         h := GetBigHandle(PixMapSize);
  1569.                         if h = nil then begin
  1570.                                 nSlices := i - 1;
  1571.                                 PutError(concat('Not enough memory to open all ', long2str(nExtraImages + 1), ' slices in the stack.'));
  1572.                                 PartialStack := true;
  1573.                                 leave;
  1574.                             end;
  1575.                         PicBaseH[i] := h;
  1576.                         CurrentSlice := i;
  1577.                         SelectSlice(i);
  1578.                         UpdateTitleBar;
  1579.                         DataSize := ImageSize;
  1580.                         err := SetFPos(f, fsFromStart, table[i - 1].offset);
  1581.                         CheckFileSize(f, DataSize, table[i - 1].offset);
  1582.                         if DataSize > 0 then
  1583.                             err := fsread(f, DataSize, h^);
  1584.                         if odd(PixelsPerLine) then
  1585.                             UnpackLines;
  1586.                         if InvertedImage then
  1587.                             InvertPic;
  1588.                         UpdatePicWindow;
  1589.                         if CommandPeriod then begin
  1590.                                 beep;
  1591.                                 if i < nSlices then
  1592.                                     PartialStack := true;
  1593.                                 nSlices := i;
  1594.                                 wait(60);
  1595.                                 leave;
  1596.                             end;
  1597.                     end; {for}
  1598.                 CurrentSlice := SaveCS;
  1599.                 if CurrentSlice > nSlices then
  1600.                     CurrentSlice := 1;
  1601.                 SelectSlice(CurrentSlice);
  1602.                 if PartialStack then begin
  1603.                         vref := 0;
  1604.                         PictureType := NewPicture;
  1605.                         title := concat(title, '@');
  1606.                     end;
  1607.                 UpdateTitleBar;
  1608.                 UpdateWindowsMenuItem;
  1609.             end;
  1610.     end;
  1611.  
  1612.  
  1613.     procedure OpenStack (f: integer);
  1614.         var
  1615.             table: TiffIFDTable;
  1616.             i, nExtraImages: integer;
  1617.             where: LongInt;
  1618.     begin
  1619.         nExtraImages := TempStackInfo.nSlices - 1;
  1620.         with info^ do begin
  1621.                 where := ImageDataOffset;
  1622.                 for i := 1 to nExtraImages do
  1623.                     with table[i] do begin
  1624.                             iWidth := PixelsPerLine;
  1625.                             iHeight := nLines;
  1626.                             where := where + ImageSize;
  1627.                             Offset := where;
  1628.                             invert := false;
  1629.                         end;
  1630.                 ReadStackSlices(f, nExtraImages, table);
  1631.             end;
  1632.     end;
  1633.  
  1634.  
  1635.     procedure OpenExtraTiffImages (f: integer; NextTiffIFD: LongInt);
  1636.         var
  1637.             table: TiffIFDTable;
  1638.             TiffInfo: TiffInfoRec;
  1639.             i, nExtraImages: integer;
  1640.             AllSameSize: boolean;
  1641.     begin
  1642.         nExtraImages := 0;
  1643.         repeat
  1644.             if not OpenTiffDirectory(f, NextTiffIFD, TiffInfo, false) then
  1645.                 exit(OpenExtraTiffImages);
  1646.             nExtraImages := nExtraImages + 1;
  1647.             with TiffInfo, table[nExtraImages] do begin
  1648.                     iWidth := width;
  1649.                     iHeight := height;
  1650.                     Offset := OffsetToData;
  1651.                     invert := ZeroIsBlack;
  1652.                     NextTiffIFD := NextIFD;
  1653.                 end;
  1654.         until (NextTiffIFD = 0) or (nExtraImages = MaxSlices);
  1655.         AllSameSize := true;
  1656.         with info^ do begin
  1657.                 for i := 1 to nExtraImages do
  1658.                     AllSameSize := AllSameSize and (PixelsPerLine = table[i].iWidth) and (nLines = table[i].iHeight);
  1659.                 if AllSameSize and not odd(PixelsPerLine) then
  1660.                     ReadStackSlices(f, nExtraImages, table);
  1661.             end;
  1662.     end;
  1663.  
  1664.     procedure OpenRGBTiff(f: integer);
  1665.     const
  1666.         bufsize = 12000;
  1667.     var
  1668.         i, row, pixel, rgbPixel, ignore, SaveRow: integer;
  1669.         NextUpdate, count: LongInt;
  1670.         buffer: packed array [0 .. bufsize] of byte;
  1671.         rLine, gLine, bLine: LineType;
  1672.         err: OSErr;
  1673.         MaskRect: rect;
  1674.     begin
  1675.         with info^ do begin
  1676.             if PixelsPerLine > MaxLine then
  1677.                 exit(OpenRGBTiff);
  1678.             if not MakeStackFromWindow then
  1679.                 exit(OpenRGBTiff);
  1680.             if not AddSlice(false) then begin
  1681.                     info^.changes := false;
  1682.                     ignore := CloseAWindow(info^.wptr);
  1683.                     exit(OpenRGBTiff);
  1684.                 end;
  1685.             if not AddSlice(false) then begin
  1686.                     info^.changes := false;
  1687.                     ignore := CloseAWindow(info^.wptr);
  1688.                     exit(OpenRGBTiff);
  1689.                 end;
  1690.             SaveRow:=0;
  1691.             NextUpdate:=TickCount+6;
  1692.             err := SetFPos(f, fsFromStart, ImageDataOffset);
  1693.             count := 0;
  1694.             for row:=0 to nLines - 1 do begin
  1695.                 for pixel := 0 to PixelsPerLine - 1 do begin
  1696.                     if count <= 0 then begin
  1697.                         count := bufsize;
  1698.                         err := fsread(f, count, @buffer);
  1699.                         if err <> -39 then {eof error}
  1700.                             if CheckIO(err) <> noErr then
  1701.                                 exit(OpenRGBTiff);
  1702.                         rgbPixel := 0;
  1703.                     end;
  1704.                     rLine[pixel] := 255 - buffer[rgbPixel];
  1705.                     gLine[pixel] := 255 - buffer[rgbPixel + 1];
  1706.                     bLine[pixel] := 255 - buffer[rgbPixel + 2];
  1707.                     rgbPixel := rgbPixel + 3;
  1708.                     count := count - 3;
  1709.                 end;
  1710.                 SelectSlice(1);
  1711.                 PutLine(0, row, PixelsPerLine, rLine);
  1712.                 if TickCount>=NextUpdate then begin
  1713.                     SetRect(MaskRect, 0, SaveRow, PixelsPerLine, row+1);
  1714.                     UpdateScreen(MaskRect);
  1715.                     SaveRow:=row + 1;
  1716.                     NextUpdate:=TickCount+6;
  1717.                 end;
  1718.                 SelectSlice(2);
  1719.                 PutLine(0, row, PixelsPerLine, gLine);
  1720.                 SelectSlice(3);
  1721.                 PutLine(0, row, PixelsPerLine, bLine);
  1722.             end; {for}
  1723.             with StackInfo^ do begin
  1724.                 CurrentSlice := 1;
  1725.                 SelectSlice(CurrentSlice);
  1726.                 StackType := rgbStack;
  1727.             end;
  1728.             SetRect(MaskRect, 0, SaveRow, PixelsPerLine, nLines);
  1729.             UpdateScreen(MaskRect);
  1730.             UpdateTitleBar;
  1731.             ResetGrayMap;
  1732.             OpeningRGB := true;
  1733.         end; {with}
  1734.     end;
  1735.     
  1736.  
  1737.     function OpenFile (fname: str255; vnum: integer): boolean;
  1738.         var
  1739.             ticks, ByteCount, i, DataSize, NextTiffIFD: LongInt;
  1740.             err: OSErr;
  1741.             f: integer;
  1742.             line, pixel: integer;
  1743.             iptr, p: ptr;
  1744.             SaveInfo: InfoPtr;
  1745.             TiffInfo: TiffInfoRec;
  1746.             isRGBTiff: boolean;
  1747.     begin
  1748.         OpenFile := false;
  1749.         ShowWatch;
  1750.         err := fsopen(fname, vNum, f);
  1751.         SaveInfo := Info;
  1752.         iptr := NewPtr(SizeOf(PicInfo));
  1753.         if iptr = nil then begin
  1754.                 PutMemoryAlert;
  1755.                 err := fsclose(f);
  1756.                 exit(OpenFile)
  1757.             end;
  1758.         Info := pointer(iptr);
  1759.         CloneInfo(SaveInfo^, Info^);
  1760.         with Info^ do begin
  1761.                 ColorMapOffset := 0;
  1762.                 if not OpenHeader(f, fname, vnum, TiffInfo) then begin
  1763.                         DisposePtr(iptr);
  1764.                         err := fsclose(f);
  1765.                         Info := SaveInfo;
  1766.                         exit(OpenFile)
  1767.                     end;
  1768.                 if WhatToOpen = OpenTIFF then begin
  1769.                     NextTiffIFD := TiffInfo.NextIFD;
  1770.                     isRGBTiff := TiffInfo.SamplesPerPixel = 3;
  1771.                 end else begin
  1772.                     NextTiffIFD := 0;
  1773.                     isRGBTiff := false;
  1774.                 end;
  1775.                 p := GetImageMemory(SaveInfo);
  1776.                 if p = nil then begin
  1777.                         err := fsclose(f);
  1778.                         exit(OpenFile)
  1779.                     end;
  1780.                 PicBaseAddr := p;
  1781.                 MakeNewWindow(fname);
  1782.                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  1783.                 if PictureType = FourBitTIFF then
  1784.                     Read4BitTIFF(f)
  1785.                 else if not isRGBTiff then begin
  1786.                         DataSize := nlines * PixelsPerLine;
  1787.                         CheckFileSize(f, DataSize, ImageDataOffset);
  1788.                         if DataSize > 0 then
  1789.                             err := fsread(f, DataSize, PicBaseAddr);
  1790.                         if CheckIO(err) <> NoErr then begin
  1791.                                 err := fsclose(f);
  1792.                                 exit(OpenFile)
  1793.                             end;
  1794.                     end;
  1795.                 if odd(PixelsPerLine) and (PictureType <> FourBitTiff) then
  1796.                     UnpackLines;
  1797.                 if (PictureType = Imported) and (ImportInvert or (WhatToImport = ImportMCID)) then
  1798.                     InvertedImage := true;
  1799.                 if InvertedImage then
  1800.                     InvertPic;
  1801.                 if PictureType = FourBitTIFF then
  1802.                     PictureType := imported;
  1803.                 if (ColorMapOffset > 0) and (fileVersion = 0) then begin
  1804.                         FixColors; {Fix colors, if necessary, of imported color TIFF files.}
  1805.                         WhatToUndo := NothingToUndo;
  1806.                     end;
  1807.                 vref := vnum;
  1808.                 if PixMapSize > UndoBufSize then
  1809.                     PutWarning;
  1810.                 revertable := true;
  1811.             end; {with}
  1812.             if isRGBTiff then
  1813.                 OpenRGBTiff(f)
  1814.             else if TempStackInfo.nSlices > 0 then
  1815.                 OpenStack(f)
  1816.             else if NextTiffIFD > 0 then
  1817.             OpenExtraTiffImages(f, NextTiffIFD);
  1818.         err := fsclose(f);
  1819.         OpenFile := true;
  1820.     end;
  1821.  
  1822.  
  1823. {$PUSH}
  1824. {$D-}
  1825.  
  1826.     procedure ScaleToEightBits (f: integer);
  1827.         type
  1828.             PixelLUTType = packed array[0..65535] of byte;
  1829.             PixelLUTPtr = ^PixelLUTType;
  1830.             IntLineType = array[0..MaxLine] of integer;
  1831.         var
  1832.             line: LineType;
  1833.             i, j, value, LineSize, offset: LongInt;
  1834.             ScaleFactor: extended;
  1835.             hloc, vloc, wwidth, wheight, IntValue, SaveBytesPerRow: integer;
  1836.             PixelLUT: PixelLUTPtr;
  1837.             str1, str2: str255;
  1838.             err: integer;
  1839.             aLine: IntLineType;
  1840.             LinesPerUpdate: integer;
  1841.  
  1842.         procedure reset;
  1843.             var
  1844.                 DataSize, SliceOffset: LongInt;
  1845.                 p: ptr;
  1846.         begin
  1847.             with info^ do begin
  1848.                     if StackInfo <> nil then
  1849.                         SliceOffset := ImageSize * 2 * (StackInfo^.CurrentSlice - 1)
  1850.                     else
  1851.                         SliceOffset := 0;
  1852.                     err := SetFPos(f, fsFromStart, ImageDataOffset + SliceOffset);
  1853.                     if DataH <> nil then begin
  1854.                             if offset = -1 then begin
  1855.                                     hlock(DataH);
  1856.                                     DataSize := ImageSize * 2;
  1857.                                     CheckFileSize(f, DataSize, ImageDataOffset);
  1858.                                     if DataSize > 0 then
  1859.                                         err := fsread(f, DataSize, DataH^);
  1860.                                 end;
  1861.                             offset := 0
  1862.                         end;
  1863.                 end;
  1864.         end;
  1865.  
  1866.  
  1867.         procedure GetIntLine (var line: IntLineType);
  1868.             type
  1869.                 atype = packed array[1..2] of char;
  1870.             var
  1871.                 p: ptr;
  1872.                 a: atype;
  1873.                 c: char;
  1874.                 i: integer;
  1875.         begin
  1876.             with info^ do begin
  1877.                     if DataH <> nil then begin
  1878.                             p := ptr(ord4(DataH^) + offset);
  1879.                             if (offset + LineSize) <= (PixMapSize * 2) then
  1880.                                 BlockMove(p, @line, LineSize);
  1881.                             offset := offset + LineSize;
  1882.                         end
  1883.                     else
  1884.                         err := fsread(f, LineSize, @line);
  1885.                     if LittleEndian then
  1886.                         for i := 0 to LineSize div 2 - 1 do begin
  1887.                                 a := atype(line[i]);
  1888.                                 c := a[1];
  1889.                                 a[1] := a[2];
  1890.                                 a[2] := c;
  1891.                                 line[i] := integer(a)
  1892.                             end;
  1893.                 end;
  1894.         end;
  1895.         
  1896.         procedure FindMinAndMax;
  1897.         var
  1898.             vloc, hloc: integer;
  1899.             value: LongInt;
  1900.         begin
  1901.             with info^ do begin
  1902.                 AbsoluteMin := 999999;
  1903.                 AbsoluteMax := -999999;
  1904.                 for vloc := 0 to nlines - 1 do begin
  1905.                         if (vloc mod LinesPerUpdate) = 0 then
  1906.                             ShowAnimatedWatch;
  1907.                         GetIntLine(aLine);
  1908.                         for hloc := 0 to PixelsPerLine - 1 do begin
  1909.                                 value := aLine[hloc];
  1910.                                 if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1911.                                     value := value + 65536;
  1912.                                 if value > AbsoluteMax then
  1913.                                     AbsoluteMax := value;
  1914.                                 if value < AbsoluteMin then begin
  1915.                                     if ImportingDicom then begin
  1916.                                         if value <> -32767 then AbsoluteMin := value
  1917.                                     end else
  1918.                                         AbsoluteMin := value;
  1919.                                 end; {value <AbsoluteMin}
  1920.                             end {for hloc:=}
  1921.                     end;{for vloc := }
  1922.                 if (CurrentMin = 0) and (CurrentMax = 0) then begin
  1923.                         CurrentMin := AbsoluteMin;
  1924.                         CurrentMax := AbsoluteMax;
  1925.                     end;
  1926.                 reset;
  1927.             end; {with}
  1928.         end;
  1929.  
  1930.     begin
  1931.         with info^ do begin
  1932.                 PixelLUT := PixelLUTPtr(NewPtr(SizeOf(PixelLUTType)));
  1933.                 if PixelLUT = nil then begin
  1934.                         if DataH <> nil then begin
  1935.                                 DisposeHandle(DataH);
  1936.                                 DataH := nil
  1937.                             end;
  1938.                         PutError('Not enough memory to do 16 to 8-bit scaling.');
  1939.                         AbortMacro;
  1940.                         exit(ScaleToEightBits);
  1941.                     end;
  1942.                 offset := -1;
  1943.                 reset;
  1944.                 LineSize := PixelsPerLine * 2;
  1945.                 LinesPerUpdate := 40000 div LineSize;
  1946.                 if (AbsoluteMin = 0) and (AbsoluteMax = 0) then
  1947.                     FindMinAndMax;
  1948.                 str1 := concat('min=', long2str(CurrentMin), ' (', long2str(AbsoluteMin), ')', crStr, 'max=', long2str(CurrentMax), ' (', long2str(AbsoluteMax), ')');
  1949.                 ScaleFactor := 253.0 / (CurrentMax - CurrentMin);
  1950.                 RealToString(ScaleFactor, 1, 4, str2);
  1951.                 ShowMessage(concat(str1, crStr, 'scale factor= ', str2));
  1952.                 j := 0;
  1953.                 for i := CurrentMin to CurrentMax do begin
  1954.                         PixelLUT^[j] := round((i - CurrentMin) * ScaleFactor + 1);
  1955.                         j := j + 1;
  1956.                     end;
  1957.                 for vloc := 0 to nlines - 1 do begin
  1958.                         if (vloc mod LinesPerUpdate) = 0 then
  1959.                             ShowAnimatedWatch;
  1960.                         GetIntLine(aLine);
  1961.                         for hloc := 0 to PixelsPerLine - 1 do begin
  1962.                                 value := aLine[hloc];
  1963.                                 if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1964.                                     value := value + 65536;
  1965.                                 if value < CurrentMin then
  1966.                                     value := CurrentMin;
  1967.                                 if value > CurrentMax then
  1968.                                     value := CurrentMax;
  1969.                                 line[hloc] := PixelLUT^[value - CurrentMin];
  1970.                                 i := i + 1;
  1971.                             end;
  1972.                         PutLine(0, vloc, PixelsPerLine, line);
  1973.                     end;
  1974.                 if fit = StraightLine then begin
  1975.                         nCoefficients := 2;
  1976.                         coefficient[2] := (CurrentMin - CurrentMax) / 253.0;
  1977.                         coefficient[1] := CurrentMax - coefficient[2];
  1978.                         nKnownValues := 0;
  1979.                         ZeroClip := false;
  1980.                         UpdateTitleBar;
  1981.                     end;
  1982.                 DisposePtr(ptr(PixelLUT));
  1983.                 if DataH <> nil then begin
  1984.                         DisposeHandle(DataH);
  1985.                         DataH := nil
  1986.                     end;
  1987.             end; {with}
  1988.     end;
  1989.  
  1990.  
  1991.     procedure RescaleToEightBits;
  1992.         var
  1993.             range: LongInt;
  1994.             err: OSErr;
  1995.             f: integer;
  1996.     begin
  1997.         with info^ do begin
  1998.                 ShowWatch;
  1999.                 KillRoi;
  2000.                 DisableDensitySlice;
  2001.                 err := fsopen(title, vref, f);
  2002.                 if CheckIO(err) <> 0 then
  2003.                     exit(RescaleToEightBits);
  2004.                 range := CurrentMax - CurrentMin;
  2005.                 if ColorStart > 0 then
  2006.                     CurrentMax := CurrentMax - round((ColorStart / 255.0) * range)
  2007.                 else
  2008.                     CurrentMax := AbsoluteMax;
  2009.                 if ColorEnd < 255 then
  2010.                     CurrentMin := CurrentMin + round(((255 - ColorEnd) / 255.0) * range)
  2011.                 else
  2012.                     CurrentMin := AbsoluteMin;
  2013.                 ScaleToEightBits(f);
  2014.                 err := fsclose(f);
  2015.                 InvertPic;
  2016.                 UpdatePicWindow;
  2017.                 ResetMap;
  2018.                 if fit <> uncalibrated then
  2019.                     GenerateValues;
  2020.             end;
  2021.     end;
  2022.  
  2023.  
  2024.     procedure Import16BitSlices (f: integer);
  2025.         var
  2026.             i, err: integer;
  2027.             h: handle;
  2028.             DataSize, nImages, MaxImages, FileSize: LongInt;
  2029.     begin
  2030.         with info^ do begin
  2031.                 nImages := ImportCustomSlices;
  2032.                 err := GetEof(f, FileSize);
  2033.                 MaxImages := (FileSize - ImportCustomOffset) div (ImageSize * 2);
  2034.                 if nImages > MaxImages then
  2035.                     nImages := MaxImages;
  2036.                 if nImages < 2 then
  2037.                     exit(Import16BitSlices);
  2038.                 ShowMessage(CmdPeriodToStop);
  2039.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  2040.                 if StackInfo = nil then
  2041.                     exit(Import16BitSlices);
  2042.             end; {with}
  2043.         with info^, info^.StackInfo^ do begin
  2044.                 nSlices := nImages;
  2045.                 SliceSpacing := 0.0;
  2046.                 FrameInterval := 0.0;
  2047.                 StackType := VolumeStack;
  2048.                 PicBaseH[1] := PicBaseHandle;
  2049.                 revertable := false;
  2050.                 for i := 2 to nSlices do begin
  2051.                         h := NewHandle(PixMapSize);
  2052.                         if h = nil then begin
  2053.                                 nSlices := i - 1;
  2054.                                 leave;
  2055.                             end;
  2056.                         PicBaseH[i] := h;
  2057.                         CurrentSlice := i;
  2058.                         SelectSlice(i);
  2059.                         UpdateTitleBar;
  2060.                         DataSize := ImageSize;
  2061.                         AbsoluteMin := 0;
  2062.                         AbsoluteMax := 0;
  2063.                         CurrentMin := 0;
  2064.                         CurrentMax := 0;
  2065.                         if not ImportAutoScale then begin
  2066.                                 if ((ImportMax - ImportMin) > 65536.0) or (ImportMin > ImportMax) then begin
  2067.                                         ImportMin := 0.0;
  2068.                                         ImportMax := 255;
  2069.                                     end;
  2070.                                 CurrentMin := round(ImportMin);
  2071.                                 CurrentMax := round(ImportMax);
  2072.                             end;
  2073.                         ScaleToEightBits(f);
  2074.                         InvertPic;
  2075.                         UpdatePicWindow;
  2076.                         if CommandPeriod then begin
  2077.                                 beep;
  2078.                                 nSlices := i;
  2079.                                 wait(60);
  2080.                                 leave;
  2081.                             end;
  2082.                     end; {for}
  2083.                 if (MaxBlock < MinFree) and (nSlices > 1) then begin
  2084.                         repeat
  2085.                             DisposeHandle(PicBaseH[nSlices]);
  2086.                             nSlices := nSlices - 1;
  2087.                         until (MaxBlock > MinFree) or (nSlices = 1);
  2088.                         PutError(concat('Not enough memory to open all ', long2str(nImages), ' slices in the stack.'));
  2089.                     end;
  2090.                 CurrentSlice := 1;
  2091.                 SelectSlice(CurrentSlice);
  2092.                 if ImportCalibrate and  ImportAutoScale then begin
  2093.                     RemoveDensityCalibration;
  2094.                     ImportCalibrate := false;
  2095.                 end;
  2096.                 UpdateTitleBar;
  2097.                 UpdateWindowsMenuItem;
  2098.             end;
  2099.     end;
  2100.  
  2101.  
  2102.     function Import16BitFile (fname: str255; vnum: integer): boolean;
  2103.         var
  2104.             ticks, ByteCount, i: LongInt;
  2105.             err: OSErr;
  2106.             f: integer;
  2107.             line, pixel: integer;
  2108.     begin
  2109.         Import16BitFile := false;
  2110.         if ImportCustomWidth > MaxLine then
  2111.             exit(Import16BitFile);
  2112.         if not NewPicWindow(fname, ImportCustomWidth, ImportCustomHeight) then
  2113.             exit(Import16BitFile);
  2114.         ShowWatch;
  2115.         err := fsopen(fname, vNum, f);
  2116.         with info^ do begin
  2117.                 PictureType := imported;
  2118.                 ImageDataOffset := ImportCustomOffset;
  2119.                 DataType := ImportCustomDepth;
  2120.                 vref := vnum;
  2121.                 AbsoluteMin := 0;
  2122.                 AbsoluteMax := 0;
  2123.                 CurrentMin := 0;
  2124.                 CurrentMax := 0;
  2125.                 LittleEndian := ImportSwapBytes;
  2126.                 if ImportCalibrate then begin
  2127.                     fit := StraightLine;
  2128.                     nCoefficients := 2;
  2129.                     coefficient[1] := 0.0; {ScaleToEightBits changes these coefficient}
  2130.                     coefficient[2] := 1.0;
  2131.                 end else
  2132.                     RemoveDensityCalibration;
  2133.                 if not ImportAutoScale then begin
  2134.                         if ((ImportMax - ImportMin) > 65536.0) or (ImportMin > ImportMax) then begin
  2135.                                 ImportMin := 0.0;
  2136.                                 ImportMax := 255;
  2137.                             end;
  2138.                         CurrentMin := round(ImportMin);
  2139.                         CurrentMax := round(ImportMax);
  2140.                     end;
  2141.                 DataH := GetBigHandle(PixMapSize * 2);
  2142.                 ScaleToEightBits(f);
  2143.                 if ImportCustomSlices > 1 then
  2144.                     Import16BitSlices(f);
  2145.                 err := fsclose(f);
  2146.                 InvertPic;
  2147.                 if PixMapSize > UndoBufSize then
  2148.                     PutWarning;
  2149.                 revertable := false;
  2150.             end; {with}
  2151.         Import16BitFile := true;
  2152.     end;
  2153.  
  2154.  
  2155.     procedure InitPictBuffer (howBig: LongInt);
  2156.     begin
  2157.         repeat
  2158.             PictBuffer := NewPtr(howBig);
  2159.             if PictBuffer = nil then
  2160.                 howBig := howBig div 2;
  2161.         until PictBuffer <> nil;
  2162.         DisposePtr(PictBuffer);
  2163.         PictBuffer := NewPtr(howBig div 2);
  2164.     end;
  2165.  
  2166.  
  2167.     procedure FillPictBuffer;
  2168.         var
  2169.             count: LongInt;
  2170.             err: OSErr;
  2171.     begin
  2172.         count := GetPtrSize(PictBuffer);
  2173.         if not fitsInPictBuffer then begin
  2174.                 err := FSRead(PictF, count, PictBuffer);
  2175.                 if err <> NoErr then
  2176.                     PictReadErr := true;
  2177.             end;
  2178.         bytesInPictBuffer := count;
  2179.         curPictBufPtr := PictBuffer;
  2180.     end;
  2181.  
  2182.  
  2183.     procedure GetPICTData (dataPtr: Ptr; byteCount: Integer);
  2184.     {Input picture spooler routine taken from Apple's PICTViewer example program.}
  2185.         var
  2186.             count: LongInt;
  2187.             anErr: OSErr;
  2188.     begin
  2189.         count := byteCount;
  2190.         repeat
  2191.             if bytesInPictBuffer >= count then begin
  2192.                     BlockMove(curPictBufPtr, dataPtr, count);
  2193.                     curPictBufPtr := Ptr(Ord4(curPictBufPtr) + count);
  2194.                     bytesInPictBuffer := bytesInPictBuffer - count;
  2195.                     count := 0;
  2196.                 end
  2197.             else begin        {Not enough in buffer}
  2198.                     if bytesInPictBuffer > 0 then begin
  2199.                             BlockMove(curPictBufPtr, dataPtr, bytesInPictBuffer);
  2200.                             dataPtr := Ptr(Ord4(dataPtr) + bytesInPictBuffer);
  2201.                             count := count - bytesInPictBuffer;
  2202.                         end;
  2203.                     FillPictBuffer;
  2204.                 end;
  2205.         until count = 0;
  2206.     end;
  2207.  
  2208.  
  2209.     procedure BitInfo (var srcBits: PixMap; var srcRect, dstRect: rect; mode: integer; maskRgn: rgnHandle);
  2210.         var
  2211.             i, size: integer;
  2212.     begin
  2213.         if BitInfoCount = 0 then begin
  2214.                 PictSrcRect := srcRect;
  2215.                 if srcBits.rowBytes < 0 then
  2216.                     with srcBits.pmTable^^ do begin {Make sure it is a PixMap.}
  2217.                             size := ctSize;
  2218.                             if size > 255 then
  2219.                                 size := 255;
  2220.                             if size > 0 then begin
  2221.                                     BitInfoCount := BitInfoCount + 1;
  2222.                                     if not UseExistingLUT then
  2223.                                         with info^ do begin
  2224.                                                 for i := 0 to size do
  2225.                                                     cTable[i].rgb := ctTable[i].rgb;
  2226.                                                 LutMode := ColorLut;
  2227.                                                 SetupPseudocolor;
  2228.                                             end;
  2229.                                 end;
  2230.                         end; {with}
  2231.             end;
  2232.     end;
  2233.  
  2234.  
  2235.     procedure GetLUTFromPict (thePict: PicHandle);
  2236.   {Refer to "Screen Dump FKEY for Color Picts", February 1988 MacTutor.}
  2237.         type
  2238.             myPicData = record
  2239.                     p: Picture;
  2240.                     ID: integer
  2241.                 end;
  2242.             myPicPtr = ^myPicData;
  2243.             myPicHdl = ^myPicPtr;
  2244.         var
  2245.             tempProcs: CQDProcs;
  2246.             SavePort: GrafPtr;
  2247.             err: osErr;
  2248.             TempPort: CGrafPort;
  2249.             limbo: rect;
  2250.             xxscale, yyscale: extended;
  2251.     begin
  2252.         GetPort(SavePort);
  2253.         OpenCPort(@TempPort);
  2254.         SetStdCProcs(tempProcs);
  2255.         tempProcs.bitsProc := BitInfoProc;
  2256.         tempProcs.getPicProc := GetPICTDataProc;
  2257.         PictSrcRect := thePict^^.picFrame;
  2258.         BitInfoCount := 0;
  2259.         TempPort.grafProcs := @tempProcs;
  2260.         err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  2261.         FillPictBuffer;
  2262.         limbo := thePict^^.picFrame;
  2263.         OffsetRect(limbo, 10000, 10000);
  2264.         if not PictReadErr then
  2265.             DrawPicture(thePict, limbo);
  2266.         CloseCPort(@TempPort);
  2267.         SetPort(SavePort);
  2268.         with info^, PictSrcRect do begin
  2269.                 LoadLUT(cTable);
  2270.                 xxScale := (right - left) / PixelsPerLine;
  2271.                 yyScale := (bottom - top) / nLines;
  2272.                 if (xxScale > 1.0) and ((PixelsPerLine * xxScale) <= MaxLine) and ((xxScale - yyScale) < 0.1) then begin
  2273.                         PixelsPerLine := right - left;
  2274.                         nLines := bottom - top;
  2275.                     end;
  2276.             end; {with}
  2277.     end;
  2278.  
  2279.  
  2280.     function OpenPict;{(fname:str255; vnum:integer; Reverting:boolean):boolean}
  2281.         var
  2282.             err: OSErr;
  2283.             i: integer;
  2284.             iptr, p: ptr;
  2285.             PictSize, HowBig: LongInt;
  2286.             thePict: PicHandle;
  2287.             tPort: GrafPtr;
  2288.             tempProcs: CQDProcs;
  2289.             SaveProcsPtr: QDProcsPtr;
  2290.             SaveInfo: InfoPtr;
  2291.             SaveGDevice: GDHandle;
  2292.             TiffInfo: TiffInfoRec;
  2293.  
  2294.         procedure Abort;
  2295.         begin
  2296.             if not reverting then begin
  2297.                     DisposePtr(pointer(Info));
  2298.                     Info := SaveInfo;
  2299.                     LoadLUT(info^.cTable);
  2300.                 end;
  2301.             if thePict <> nil then
  2302.                 DisposeHandle(handle(thePict));
  2303.             if PictF <> 0 then
  2304.                 err := fsclose(PictF);
  2305.             {exit(OpenPict);} {ppc-bug}
  2306.         end;
  2307.  
  2308.     begin
  2309.         if BitInfoProc=nil
  2310.             then BitInfoProc:=NewRoutineDescriptor(@BitInfo, uppQDBitsProcInfo, GetCurrentISA);
  2311.         if GetPictDataProc=nil
  2312.             then GetPictDataProc:=NewRoutineDescriptor(@GetPictData, uppQDGetPicProcInfo, GetCurrentISA);
  2313.         PictF := 0;
  2314.         thePict := nil;
  2315.         OpenPict := false;
  2316.         PictReadErr := false;
  2317.         ShowWatch;
  2318.         SaveInfo := Info;
  2319.         err := fsopen(fname, vNum, PictF);
  2320.         if CheckIO(err) <> 0 then begin
  2321.             Abort;
  2322.             exit(OpenPict)
  2323.         end;
  2324.         if not Reverting then begin
  2325.                 iptr := NewPtr(SizeOf(PicInfo));
  2326.                 if iptr = nil then begin
  2327.                         PutMemoryAlert;
  2328.                         err := fsclose(PictF);
  2329.                         exit(OpenPict)
  2330.                     end;
  2331.                 Info := pointer(iptr);
  2332.                 CloneInfo(SaveInfo^, Info^);
  2333.             end;
  2334.         with Info^ do begin
  2335.                 err := GetEof(PictF, PictSize);
  2336.                 if CheckIO(err) <> 0 then begin
  2337.                     Abort;
  2338.                     exit(OpenPict)
  2339.                 end;
  2340.                 PictSize := PictSize - 512;
  2341.                 if PictSize <= 0 then begin
  2342.                     Abort;
  2343.                     exit(OpenPict)
  2344.                 end;
  2345.                 WhatToOpen := OpenPICT2;
  2346.                 if not OpenHeader(PictF, fname, vnum, TiffInfo) then begin
  2347.                     Abort;
  2348.                     exit(OpenPict)
  2349.                 end;
  2350.                 thePict := PicHandle(NewHandle(SizeOf(Picture)));
  2351.                 if thePict = nil then begin
  2352.                     Abort;
  2353.                     exit(OpenPict);
  2354.                 end;
  2355.                 err := SetFPos(PictF, fsFromStart, 512);
  2356.                 if CheckIO(err) <> 0 then begin
  2357.                     Abort;
  2358.                     exit(OpenPict)
  2359.                 end;
  2360.                 howBig := SizeOf(Picture);
  2361.                 err := FSRead(PictF, howBig, Pointer(thePict^));
  2362.                 if CheckIO(err) <> 0 then begin
  2363.                     Abort;
  2364.                     exit(OpenPict)
  2365.                 end;
  2366.                 with thePict^^.PicFrame do begin
  2367.                         nlines := bottom - top;
  2368.                         PixelsPerLine := right - left;
  2369.                     end;
  2370.          {....}
  2371.                 err := GetEof(PictF, howBig);
  2372.                 howBig := howBig - (512 + SizeOf(Picture));
  2373.                 InitPictBuffer(HowBig * 2);
  2374.                 if GetPtrSize(PictBuffer) >= howBig then begin
  2375.                         err := FSRead(PictF, howBig, PictBuffer);
  2376.                         if CheckIO(err) <> NoErr then begin
  2377.                                 DisposeHandle(handle(thePict));
  2378.                                 DisposePtr(PictBuffer);
  2379.                                 err := fsclose(PictF);
  2380.                                 exit(OpenPict)
  2381.                             end;
  2382.                         fitsInPictBuffer := true;
  2383.                     end
  2384.                 else
  2385.                     fitsInPictBuffer := false;
  2386.                 if (LutMode = ColorLut) or (LutMode = CustomGrayscale) or (fileVersion = 0) then
  2387.                     GetLUTFromPict(thePict);
  2388.                 if not Reverting then begin
  2389.                         p := GetImageMemory(SaveInfo);
  2390.                         if p = nil then begin
  2391.                                 DisposeHandle(handle(thePict));
  2392.                                 DisposePtr(PictBuffer);
  2393.                                 err := fsclose(PictF);
  2394.                                 exit(OpenPict)
  2395.                             end;
  2396.                         PicBaseAddr := p;
  2397.                         MakeNewWindow(fname);
  2398.                         if ScreenDepth <> 8 then begin
  2399.                             SelectAll(false);
  2400.                             DoOperation(EraseOp);
  2401.                             KillRoi;
  2402.                         end;
  2403.                     end;
  2404.                 if (PixMapSize > UndoBufSize) and (not Reverting) then begin
  2405.                         PutWarning;
  2406.                         ShowWatch;
  2407.                     end;
  2408.                 if isGrayScaleLUT then
  2409.                     ResetGrayMap;
  2410.                 SaveGDevice := GetGDevice;
  2411.                 SetGDevice(osGDevice);
  2412.                 GetPort(tPort);
  2413.                 SetPort(GrafPtr(osPort));
  2414.                 pmForeColor(BlackIndex);
  2415.                 pmBackColor(WhiteIndex);
  2416.                 RGBForeColor(BlackRGB);
  2417.                 RGBBackColor(WhiteRGB);
  2418.                 EraseRect(PicRect);
  2419.                 SaveProcsPtr := pointer(osPort^.grafProcs);
  2420.                 SetStdCProcs(tempProcs);
  2421.                 tempProcs.getPicProc := GetPICTDataProc;
  2422.                 osPort^.grafProcs := @TempProcs;
  2423.                 err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  2424.                 FillPictBuffer;
  2425.                 if not PictReadErr then
  2426.                     DrawPicture(thePict, PicRect);
  2427.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  2428.                 DisposeHandle(handle(thePict));
  2429.                 DisposePtr(PictBuffer);
  2430.                 pmForeColor(ForegroundIndex);
  2431.                 pmBackColor(BackgroundIndex);
  2432.                 SetPort(tPort);
  2433.                 SetGDevice(SaveGDevice);
  2434.                 vref := vnum;
  2435.                 PictureType := PictFile;
  2436.                 revertable := true;
  2437.             end; {with}
  2438.         err := fsclose(PictF);
  2439.         SetupUndo;
  2440.         if not PictReadErr then
  2441.             OpenPict := true;
  2442.     end;
  2443.  
  2444.  
  2445.     procedure GetCLUT (thePict: PicHandle);
  2446.         type
  2447.             myPicData = record
  2448.                     p: Picture;
  2449.                     ID: integer
  2450.                 end;
  2451.             myPicPtr = ^myPicData;
  2452.             myPicHdl = ^myPicPtr;
  2453.         var
  2454.             tempProcs: CQDProcs;
  2455.             SaveProcsPtr: QDProcsPtr;
  2456.             err: osErr;
  2457.     begin
  2458.         with info^ do begin
  2459.                 SetPort(GrafPtr(osPort));
  2460.                 SaveProcsPtr := pointer(wptr^.grafProcs);
  2461.                 SetStdCProcs(tempProcs);
  2462.                 tempProcs.bitsProc := BitInfoProc;
  2463.                 BitInfoCount := 0;
  2464.                 osPort^.grafProcs := @tempProcs;
  2465.                 DrawPicture(thePict, thePict^^.picFrame);
  2466.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  2467.                 LoadLUT(cTable);
  2468.             end;
  2469.     end;
  2470.  
  2471.  
  2472.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  2473.         var
  2474.             RefNum, picID, hOffset, vOffset, nPICS, i: integer;
  2475.             err: OSErr;
  2476.             PicH: PicHandle;
  2477.             h: handle;
  2478.             MemError, Aborted: boolean;
  2479.             FrameRect: rect;
  2480.             SaveGDevice: GDHandle;
  2481.     begin
  2482.         if BitInfoProc=nil
  2483.             then BitInfoProc:=NewRoutineDescriptor(@BitInfo, uppQDBitsProcInfo, GetCurrentISA);
  2484.         OpenPics := false;
  2485.         if MaxBlock < MinFree then begin
  2486.                 PutError('Insufficient memory to open PICS file.');
  2487.                 exit(OpenPICS);
  2488.             end;
  2489.         ShowWatch;
  2490.         err := SetVol(nil, fRefNum);
  2491.         RefNum := OpenResFile(name);
  2492.         if RefNum = -1 then begin
  2493.                 PutError('Unable to open PICS file.');
  2494.                 exit(OpenPICS);
  2495.             end;
  2496.         nPICS := Count1Resources('PICT');
  2497.         if nPICS < 1 then begin
  2498.                 PutError('No PICTs found.');
  2499.                 CloseResFile(RefNum);
  2500.                 exit(OpenPICS);
  2501.             end;
  2502.         PicH := GetPicture(128);
  2503.         if PicH = nil then begin
  2504.             CloseResFile(RefNum);
  2505.             exit(OpenPICS);
  2506.         end;
  2507.         FrameRect := PicH^^.PicFrame;
  2508.         with FrameRect do begin
  2509.                 hOffset := left;
  2510.                 vOffset := top;
  2511.                 right := right - hOffset;
  2512.                 bottom := bottom - vOffset;
  2513.                 left := 0;
  2514.                 top := 0;
  2515.             end;
  2516.         with FrameRect do
  2517.             if not NewPicWindow(name, right - left, bottom - top) then begin
  2518.                 CloseResFile(RefNum);
  2519.                 exit(OpenPICS);
  2520.             end;
  2521.         with info^ do begin
  2522.                 revertable := false;
  2523.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  2524.                 if StackInfo = nil then begin
  2525.                     CloseResFile(RefNum);
  2526.                     exit(OpenPICS);
  2527.                 end;
  2528.                 with StackInfo^ do begin
  2529.                         SliceSpacing := 0.0;
  2530.                         FrameInterval := 0.0;
  2531.                         StackType := VolumeStack;
  2532.                         nSlices := 1;
  2533.                         CurrentSlice := 1;
  2534.                         PicBaseH[1] := PicBaseHandle;
  2535.                     end;
  2536.             end;
  2537.         if not UseExistingLUT then
  2538.             GetCLUT(picH);
  2539.         with info^, Info^.StackInfo^ do begin
  2540.                 SaveGDevice := GetGDevice;
  2541.                 SetGDevice(osGDevice);
  2542.                 SetPort(GrafPtr(osPort));
  2543.                 pmBackColor(WhiteIndex);
  2544.                 EraseRect(PicRect);
  2545.                 DrawPicture(picH, PicRect);
  2546.                 DisposeHandle(handle(picH));
  2547.                 SetGDevice(SaveGDevice);
  2548.                 UpdatePicWindow;
  2549.                 picID := 129;
  2550.                 MemError := false;
  2551.                 for i := 2 to nPICS do begin
  2552.                         PicH := GetPicture(picID);
  2553.                         if (PicH = nil) or (ResError <> NoErr) then
  2554.                             Leave;
  2555.                         h := GetBigHandle(PixMapSize);
  2556.                         if h = nil then begin
  2557.                                 if PicH <> nil then
  2558.                                     DisposeHandle(handle(picH));
  2559.                                 MemError := true;
  2560.                                 Leave;
  2561.                             end;
  2562.                         nSlices := nSlices + 1;
  2563.                         CurrentSlice := CurrentSlice + 1;
  2564.                         PicBaseH[CurrentSlice] := h;
  2565.                         SelectSlice(CurrentSlice);
  2566.                         FrameRect := PicH^^.PicFrame;
  2567.                         with FrameRect do begin
  2568.                                 right := right - hOffset;
  2569.                                 bottom := bottom - vOffset;
  2570.                                 left := left - hOffset;
  2571.                                 top := top - vOffset;
  2572.                             end;
  2573.                         SetGDevice(osGDevice);
  2574.                         EraseRect(PicRect);
  2575.                         if not EqualRect(FrameRect, PicRect) then
  2576.                             BlockMove(PicBaseH[CurrentSlice - 1]^, PicBaseH[CurrentSlice]^, PixMapSize);
  2577.                         DrawPicture(picH, FrameRect);
  2578.                         DisposeHandle(handle(picH));
  2579.                         SetGDevice(SaveGDevice);
  2580.                         UpdatePicWindow;
  2581.                         UpdateTitleBar;
  2582.                         Aborted := CommandPeriod;
  2583.                         if Aborted then begin
  2584.                                 beep;
  2585.                                 wait(60);
  2586.                                 Leave;
  2587.                             end;
  2588.                         picID := picID + 1;
  2589.                     end;
  2590.                 CloseResFile(RefNum);
  2591.                 if MemError then
  2592.                     PutError('Not enough memory to open all images in PICS file.');
  2593.                 CurrentSlice := 1;
  2594.                 SelectSlice(CurrentSlice);
  2595.                 PictureType := PicsFile;
  2596.                 Revertable := false;
  2597.                 UpdateTitleBar;
  2598.                 UpdateWindowsMenuItem;
  2599.                 if not MemError and not Aborted then
  2600.                     OpenPICS := true;
  2601.             end; {with}
  2602.     end;
  2603.  
  2604.  
  2605. {$D-}
  2606.  
  2607.     procedure OpenAll (RefNum: integer);
  2608.       {Opens all appropriate files in a folder.    Original version contributed by Ira Rampil.}
  2609.         var
  2610.             OpenedOK: boolean;
  2611.             index,vRefNum: integer;
  2612.             name: Str255;
  2613.             ftype: OSType;
  2614.             err: OSErr;
  2615.             PB: CInfoPBRec;
  2616.             dirID,ProcID:LongInt;
  2617.     begin
  2618.         vRefNum:=0;
  2619.         err:=GetWDInfo(RefNum,vRefNum,dirID,ProcID);
  2620.         if err<>noErr then
  2621.             exit(OpenAll);
  2622.         index := 0;
  2623.         while true do begin
  2624.                 index := index + 1;
  2625.                 with PB do begin
  2626.                         ioCompletion := nil;
  2627.                         ioNamePtr := @name;
  2628.                         ioVRefNum := RefNum;
  2629.                         ioDirID:=DirID;
  2630.                         ioFDirIndex := index;
  2631.                         err := PBGetCatInfoSync(@PB); {ppc-bug}
  2632.                         if err = fnfErr then
  2633.                             exit(OpenAll);
  2634.                         ftype := ioFlFndrInfo.fdType;
  2635.                     end;
  2636.                 if ftype = 'IPIC' then begin
  2637.                         WhatToOpen := OpenImage;
  2638.                         if not OpenFile(name, RefNum) then
  2639.                             exit(OpenAll);
  2640.                     end
  2641.                 else if ftype = 'PICT' then begin
  2642.                         if not OpenPICT(name, RefNum, false) then
  2643.                             exit(OpenAll)
  2644.                     end
  2645.                 else if ftype = 'TIFF' then begin
  2646.                         WhatToOpen := OpenTiff;
  2647.                         if not OpenFile(name, RefNum) then
  2648.                             exit(OpenAll);
  2649.                     end
  2650.                 else if ftype = 'PNTG' then
  2651.                     if not OpenMacPaint(name, RefNum) then
  2652.                         exit(OpenAll);
  2653.                 if CommandPeriod or (nPics>=MaxPics) then begin
  2654.                         beep;
  2655.                         exit(OpenAll);
  2656.                     end;
  2657.             end; {while}
  2658.     end;
  2659.  
  2660.  
  2661.     function OpenDialogHook (item: integer; theDialog: DialogPtr): integer;
  2662.         const
  2663.             OpenAllID = 11;
  2664.             KeepLutID = 12;
  2665.         var
  2666.             i: integer;
  2667.     begin
  2668.         if (item = -1) and UseExistingLUT then
  2669.             SetDlogItem(theDialog, KeepLutID, 1);
  2670.         if item = OpenAllID then begin
  2671.                 OpenAllFiles := not OpenAllFiles;
  2672.                 SetDlogItem(theDialog, OpenAllID, ord(OpenAllFiles));
  2673.             end;
  2674.         if item = KeepLutID then begin
  2675.                 UseExistingLUT := not UseExistingLUT;
  2676.                 SetDlogItem(theDialog, KeepLutID, ord(UseExistingLut));
  2677.             end;
  2678.         OpenDialogHook := item;
  2679.     end;
  2680.  
  2681.  
  2682.     function isTiffFile (fname: str255; RefNum: integer): boolean;
  2683.   {Returns true if the first 16-bit word of the file contains 'MM' or 'II' and the second contains 42.}
  2684.         var
  2685.             f: integer;
  2686.             ByteCount: LongInt;
  2687.             hdr: array[1..512] of integer;
  2688.             err: OSErr;
  2689.     begin
  2690.         err := fsopen(fname, RefNum, f);
  2691.         err := SetFPos(f, fsFromStart, 0);
  2692.         ByteCount := 4;
  2693.         err := fsread(f, ByteCount, @hdr);
  2694.         isTiffFile := ((hdr[1] = $4949) and (hdr[2] = $2A00) or (hdr[1] = $4D4D) and (hdr[2] = $002A));
  2695.         err := fsclose(f);
  2696.     end;
  2697.  
  2698.  
  2699.     function DoOpen (FileName: str255; RefNum: integer): boolean;
  2700.         const
  2701.             MyDialogID = 70;
  2702.         var
  2703.             where: Point;
  2704.             reply: SFReply;
  2705.             b: boolean;
  2706.             TypeList: array[0..10] of OSType;
  2707.             FileType: OSType;
  2708.             OKToContinue: boolean;
  2709.             FinderInfo: FInfo;
  2710.             err: OSErr;
  2711.     begin
  2712.         if OpenDHookProc=nil
  2713.             then OpenDHookProc:=NewRoutineDescriptor(@OpenDialogHook, uppDlgHookProcInfo, GetCurrentISA);
  2714.         KillOperation;
  2715.         DisableDensitySlice;
  2716.         OpenAllFiles := false;
  2717.         UseExistingLUT := false;
  2718.         OKToContinue := false;
  2719.         if FileName = '' then begin
  2720.                 where.v := 50;
  2721.                 where.h := 50;
  2722.                 typeList[0] := 'IPIC';
  2723.                 typeList[1] := 'PICT';
  2724.                 typeList[2] := 'TIFF';
  2725.                 typeList[3] := 'ICOL';   {Color Tables}
  2726.                 typeList[4] := 'PX05'; {PixelPaint LUT}
  2727.                 typeList[5] := 'CLUT';  {Klutz LUT}
  2728.                 typeList[6] := 'drwC';  {Canvas LUT}
  2729.                 typeList[7] := 'PNTG';  {MacPaint}
  2730.                 typeList[8] := 'PICS';
  2731.                 typeList[9] := 'Iout';    {Outlines}
  2732.                 typeList[10] := 'TEXT';
  2733.                 SFPGetFile(Where, '', nil, 11, @TypeList, OpenDHookProc, reply, MyDialogID, nil);
  2734.                 if reply.good then
  2735.                     with reply do begin
  2736.                             FileName := fname;
  2737.                             FileType := ftype;
  2738.                             RefNum := vRefNum;
  2739.                             DefaultRefNum := RefNum;
  2740.                             DefaultFileName := fname;
  2741.                             OKToContinue := true;
  2742.                         end;
  2743.                 if reply.good and OpenAllFiles then begin
  2744.                         OpenAll(RefNum);
  2745.                         exit(DoOpen);
  2746.                     end;
  2747.             end
  2748.         else begin
  2749.                 err := GetFInfo(FileName, RefNum, FinderInfo);
  2750.                 FileType := FinderInfo.fdType;
  2751.                 OKToContinue := true;
  2752.             end;
  2753.         DoOpen := OKToContinue;
  2754.         if OKToContinue then begin
  2755.                 if FileType = 'IPIC' then begin
  2756.                         WhatToOpen := OpenImage;
  2757.                         b := OpenFile(FileName, RefNum)
  2758.                     end
  2759.                 else if FileType = 'PICT' then begin
  2760.                         b := OpenPICT(FileName, RefNum, false)
  2761.                     end
  2762.                 else if FileType = 'TIFF' then begin
  2763.                         WhatToOpen := OpenTIFF;
  2764.                         b := OpenFile(FileName, RefNum)
  2765.                     end
  2766.                 else if FileType = 'ICOL' then
  2767.                     OpenColorTable(FileName, RefNum)
  2768.                 else if FileType = 'PX05' then
  2769.                     ImportPalette('PX05', FileName, RefNum)
  2770.                 else if FileType = 'CLUT' then
  2771.                     ImportPalette('CLUT', FileName, RefNum)
  2772.                 else if FileType = 'drwC' then
  2773.                     ImportPalette('PX05', FileName, RefNum)
  2774.                 else if FileType = 'PNTG' then
  2775.                     b := OpenMacPaint(FileName, RefNum)
  2776.                 else if FileType = 'PICS' then
  2777.                     b := OpenPICS(FileName, RefNum)
  2778.                 else if FileType = 'Iout' then
  2779.                     OpenOutline(FileName, RefNum)
  2780.                 else if FileType = 'TEXT' then begin
  2781.                         if isTiffFile(FileName, RefNum) and not OptionKeyWasDown then begin
  2782.                                 WhatToOpen := OpenTIFF;
  2783.                                 b := OpenFile(FileName, RefNum)
  2784.                             end
  2785.                         else
  2786.                             b := OpenTextFile(FileName, RefNum)
  2787.                     end
  2788.                 else begin
  2789.                         WhatToOpen := OpenUnknown;
  2790.                         b := OpenFile(FileName, RefNum)
  2791.                     end;
  2792.                 info^.ScaleToFitWindow := false;
  2793.                 if macro then
  2794.                     GenerateValues;
  2795.             end;
  2796.     end;
  2797.  
  2798.  
  2799.     procedure ImportAllFiles (RefNum: integer);
  2800.         var
  2801.             OpenedOK: boolean;
  2802.             index, vRefNum: integer;
  2803.             name: Str255;
  2804.             ftype: OSType;
  2805.             err: OSErr;
  2806.             PB: CInfoPBRec;
  2807.             dirID,ProcID:LongInt;
  2808.     begin
  2809.         vRefNum:=0;
  2810.         err:=GetWDInfo(RefNum, vRefNum, dirID, ProcID);
  2811.         if err<>noErr then
  2812.             exit(ImportAllFiles);
  2813.         index := 0;
  2814.         while true do begin
  2815.                 index := index + 1;
  2816.                 with PB do begin
  2817.                         ioCompletion := nil;
  2818.                         ioNamePtr := @name;
  2819.                         ioVRefNum := RefNum;
  2820.                         ioDirID:=dirID;
  2821.                         ioFDirIndex := index;
  2822.                         err := PBGetCatInfoSync(@PB); {ppc-bug}
  2823.                         if err = fnfErr then
  2824.                             exit(ImportAllFiles);
  2825.                         ftype := ioFlFndrInfo.fdType;
  2826.                     end;
  2827.                 if (WhatToOpen = OpenCustom) and (ImportCustomDepth <> EightBits) then begin
  2828.                         if not Import16BitFile(name, RefNum) then
  2829.                             exit(ImportAllFiles);
  2830.                     end
  2831.                 else begin
  2832.                         if not OpenFile(name, RefNum) then
  2833.                             exit(ImportAllFiles);
  2834.                     end;
  2835.                 if CommandPeriod or (nPics>=MaxPics) then begin
  2836.                         beep;
  2837.                         exit(ImportAllFiles);
  2838.                     end;
  2839.             end; {while}
  2840.     end;
  2841.  
  2842.  
  2843.     procedure EditImportParameters;
  2844.         const
  2845.             WidthID = 2;
  2846.             HeightID = 3;
  2847.             OffsetID = 4;
  2848.             SlicesID = 5;
  2849.             FixedID = 6;
  2850.             MinID = 7;
  2851.             MaxID = 8;
  2852.         var
  2853.             mylog: DialogPtr;
  2854.             item, fwidth: integer;
  2855.     begin
  2856.         mylog := GetNewDialog(110, nil, pointer(-1));
  2857.         SetDNum(MyLog, WidthID, ImportCustomWidth);
  2858.         SelectdialogItemText(MyLog, WidthID, 0, 32767);
  2859.         SetDNum(MyLog, HeightID, ImportCustomHeight);
  2860.         SetDNum(MyLog, SlicesID, ImportCustomSlices);
  2861.         SetDNum(MyLog, OffsetID, ImportCustomOffset);
  2862.         SetDlogItem(MyLog, FixedID, ord(not ImportAutoScale));
  2863.         if WhatToImport = ImportText then
  2864.             fwidth := 2
  2865.         else
  2866.             fwidth := 0;
  2867.         SetDReal(MyLog, MinID, ImportMin, fwidth);
  2868.         SetDReal(MyLog, MaxID, ImportMax, fwidth);
  2869.         OutlineButton(MyLog, ok, 16);
  2870.         repeat
  2871.             ModalDialog(nil, item);
  2872.             if item = WidthID then begin
  2873.                     ImportCustomWidth := GetDNum(MyLog, WidthID);
  2874.                     if (ImportCustomWidth < 0) or (ImportCustomWidth > MaxPicSize) then begin
  2875.                             ImportCustomWidth := 512;
  2876.                             SetDNum(MyLog, WidthID, ImportCustomWidth);
  2877.                         end;
  2878.                 end;
  2879.             if item = HeightID then begin
  2880.                     ImportCustomHeight := GetDNum(MyLog, HeightID);
  2881.                     if ImportCustomHeight < 0 then begin
  2882.                             ImportCustomHeight := 512;
  2883.                             SetDNum(MyLog, HeightID, ImportCustomHeight);
  2884.                         end;
  2885.                 end;
  2886.             if item = SlicesID then begin
  2887.                     ImportCustomSlices := GetDNum(MyLog, SlicesID);
  2888.                     if ImportCustomSlices < 0 then begin
  2889.                             ImportCustomSlices := 1;
  2890.                             SetDNum(MyLog, SlicesID, ImportCustomSlices);
  2891.                         end;
  2892.                 end;
  2893.             if item = OffsetID then begin
  2894.                     ImportCustomOffset := GetDNum(MyLog, OffsetID);
  2895.                     if ImportCustomOffset < 0 then begin
  2896.                             ImportCustomOffset := 0;
  2897.                             SetDNum(MyLog, OffsetID, ImportCustomOffset);
  2898.                         end;
  2899.                 end;
  2900.             if item = FixedID then begin
  2901.                     ImportAutoScale := not ImportAutoScale;
  2902.                     SetDlogItem(mylog, FixedID, ord(not ImportAutoScale));
  2903.                 end;
  2904.             if item = MinID then begin
  2905.                     ImportMin := GetDReal(MyLog, MinID);
  2906.                     ImportAutoScale := false;
  2907.                     SetDlogItem(MyLog, FixedID, 1);
  2908.                 end;
  2909.             if item = MaxID then begin
  2910.                     ImportMax := GetDReal(MyLog, MaxID);
  2911.                     ImportAutoScale := false;
  2912.                     SetDlogItem(MyLog, FixedID, 1);
  2913.                 end;
  2914.         until item = ok;
  2915.         DisposeDialog(mylog);
  2916.     end;
  2917.  
  2918.  
  2919.     function ImportDialogHook (item: integer; myLog: DialogPtr): integer;
  2920.         const
  2921.             TiffID = 11;
  2922.             DicomID = 12;
  2923.             TextID = 13;
  2924.             LutID = 14;
  2925.             CustomID = 15;
  2926.             WidthAndHeightID = 16;
  2927.             OffsetID = 17;
  2928.             EightBitsID = 18;
  2929.             SixteenBitsUnsignedID = 19;
  2930.             SixteenBitsSignedID = 20;
  2931.             SwapBytesID = 21;
  2932.             ImportAllID = 22;
  2933.             EditID = 23;
  2934.             CalibrateID = 24;
  2935.             InvertID = 25;
  2936.  
  2937.         var
  2938.             i: integer;
  2939.  
  2940.         procedure SetRadioButtons1;
  2941.             var
  2942.                 i: integer;
  2943.         begin
  2944.             SetDlogItem(mylog, TiffID, 0);
  2945.             SetDlogItem(mylog, DicomID, 0);    
  2946.             SetDlogItem(mylog, LutID, 0);
  2947.             SetDlogItem(mylog, TextID, 0);
  2948.             SetDlogItem(mylog, CustomID, 0);
  2949.             case WhatToImport of
  2950.                 ImportTiff: 
  2951.                     SetDlogItem(mylog, TiffID, 1);
  2952.                 ImportDicom: 
  2953.                     SetDlogItem(mylog, DicomID, 1);
  2954.                 ImportLUT: 
  2955.                     SetDlogItem(mylog, LutID, 1);
  2956.                 ImportText: 
  2957.                     SetDlogItem(mylog, TextID, 1);
  2958.                 ImportCustom: 
  2959.                     SetDlogItem(mylog, CustomID, 1);
  2960.             end;
  2961.         end;
  2962.  
  2963.         procedure SetRadioButtons2;
  2964.             var
  2965.                 i: integer;
  2966.         begin
  2967.             SetDlogItem(mylog, EightBitsID, 0);
  2968.             SetDlogItem(mylog, SixteenBitsUnsignedID, 0);
  2969.             SetDlogItem(mylog, SixteenBitsSignedID, 0);
  2970.             case ImportCustomDepth of
  2971.                 EightBits: 
  2972.                     SetDlogItem(mylog, EightBitsID, 1);
  2973.                 SixteenBitsUnsigned: 
  2974.                     SetDlogItem(mylog, SixteenBitsUnsignedID, 1);
  2975.                 SixteenBitsSigned: 
  2976.                     SetDlogItem(mylog, SixteenBitsSignedID, 1);
  2977.             end;
  2978.         end;
  2979.  
  2980.         procedure ShowParameters;
  2981.             var
  2982.                 str1, str2, str3: str255;
  2983.         begin
  2984.             NumToString(ImportCustomWidth, str1);
  2985.             NumToString(ImportCustomHeight, str2);
  2986.             NumToString(ImportCustomOffset, str3);
  2987.             ParamText(str1, str2, str3, '');
  2988.         end;
  2989.  
  2990.     begin
  2991.         if item = -1 then begin {Initialize}
  2992.                 SetRadioButtons1;
  2993.                 SetRadioButtons2;
  2994.                 ShowParameters;
  2995.                 SetDlogItem(mylog, SwapBytesID, ord(ImportSwapBytes));
  2996.                 SetDlogItem(mylog, ImportAllID, ord(ImportAll));
  2997.                 SetDlogItem(mylog, InvertID, ord(ImportInvert));
  2998.                 SetDlogItem(mylog, CalibrateID, ord(ImportCalibrate));
  2999.             end;
  3000.         if (item >= TiffID) and (item <= CustomID) then begin
  3001.                 case item of
  3002.                     TiffID: 
  3003.                         WhatToImport := ImportTiff;
  3004.                     DicomID: 
  3005.                         WhatToImport := ImportDicom;    
  3006.                     LutID: 
  3007.                         WhatToImport := ImportLUT;
  3008.                     TextID: 
  3009.                         WhatToImport := ImportText;
  3010.                     CustomID: 
  3011.                         WhatToImport := ImportCustom;
  3012.                 end;
  3013.                 SetRadioButtons1;
  3014.             end;
  3015.         if item = EditID then begin
  3016.                 EditImportParameters;
  3017.                 WhatToImport := ImportCustom;
  3018.                 SetRadioButtons1;
  3019.                 ShowParameters;
  3020.                 SetDlogItem(mylog, CalibrateID, ord(ImportCalibrate));
  3021.             end;
  3022.         if (item >= EightBitsID) and (item <= SixteenBitsSignedID) then begin
  3023.                 case item of
  3024.                     EightBitsID: 
  3025.                         ImportCustomDepth := EightBits;
  3026.                     SixteenBitsUnsignedID: 
  3027.                         ImportCustomDepth := SixteenBitsUnsigned;
  3028.                     SixteenBitsSignedID: 
  3029.                         ImportCustomDepth := SixteenBitsSigned;
  3030.                 end;
  3031.                 SetRadioButtons2;
  3032.                 WhatToImport := ImportCustom;
  3033.                 SetRadioButtons1;
  3034.             end;
  3035.         if item = SwapBytesID then begin
  3036.                 ImportSwapBytes := not ImportSwapBytes;
  3037.                 SetDlogItem(mylog, SwapBytesID, ord(ImportSwapBytes));
  3038.                 WhatToImport := ImportCustom;
  3039.                 SetRadioButtons1;
  3040.             end;
  3041.         if item = ImportAllID then begin
  3042.                 ImportAll := not ImportAll;
  3043.                 SetDlogItem(mylog, ImportAllID, ord(ImportAll));
  3044.             end;
  3045.         if item = InvertID then begin
  3046.                 ImportInvert := not ImportInvert;
  3047.                 SetDlogItem(mylog, InvertID, ord(ImportInvert));
  3048.             end;
  3049.         if item = CalibrateID then begin
  3050.                 ImportCalibrate := not ImportCalibrate;
  3051.                 SetDlogItem(mylog, CalibrateID, ord(ImportCalibrate));
  3052.                 WhatToImport := ImportCustom;
  3053.                 SetRadioButtons1;
  3054.             end;
  3055.         ImportDialogHook := item;
  3056.     end;
  3057.  
  3058.  
  3059.     function ImportFile (FileName: str255; RefNum: integer): boolean;
  3060.         const
  3061.             ImportDialogID = 90;
  3062.         var
  3063.             where: Point;
  3064.             typeList: SFTypeList;
  3065.             reply: SFReply;
  3066.             b, ImportingTIFF, HasColorMap: boolean;
  3067.     begin
  3068.         if ImportDHookProc=nil
  3069.             then ImportDHookProc:=NewRoutineDescriptor(@ImportDialogHook, uppDlgHookProcInfo, GetCurrentISA);
  3070.         ImportFile := true;
  3071.         DisableDensitySlice;
  3072.         if not macro then begin
  3073.             ImportAll := false;
  3074.             if WhatToImport=ImportMCID then
  3075.                 WhatToImport:=ImportTIFF;
  3076.         end;
  3077.         if FileName = '' then begin
  3078.                 where.v := 50;
  3079.                 where.h := 50;
  3080.                 SFPGetFile(Where, '', nil, -1, @typeList, ImportDHookProc, reply, ImportDialogID, nil); 
  3081.                 if not reply.good then begin
  3082.                         ImportFile := false;
  3083.                         exit(ImportFile);
  3084.                     end;
  3085.                 with reply do begin
  3086.                         FileName := fname;
  3087.                         RefNum := vRefNum;
  3088.                         DefaultRefNum := RefNum;
  3089.                         DefaultFileName := fname;
  3090.                     end;
  3091.             end;
  3092.         if isTiffFile(FileName, RefNum) and not macro and not OptionKeyWasDown then
  3093.             WhatToImport := ImportTiff;
  3094.         ImportingTIFF := WhatToImport = ImportTiff;
  3095.         if ImportingTIFF then
  3096.             if not GetTIFFParameters(FileName, RefNum, HasColorMap) then
  3097.                 exit(ImportFile);
  3098.         case WhatToImport of
  3099.             ImportMCID: 
  3100.                 WhatToOpen := OpenImported;
  3101.             ImportCustom:  begin
  3102.                     if (ImportCustomDepth <> EightBits) and (ImportCustomWidth > MaxLine) then begin
  3103.                             PutError(concat('Maximum width of imported 16-bit images is ', long2str(MaxLine), '.'));
  3104.                             exit(ImportFile);
  3105.                         end;
  3106.                     WhatToOpen := OpenCustom;
  3107.                 end;
  3108.             ImportDicom: 
  3109.                begin    
  3110.                     ImportDicomImages(FileName, RefNum, ImportAll, Import16BitFile);
  3111.                     exit(ImportFile);
  3112.                end
  3113.             ImportLUT:  begin
  3114.                     DoImportLut(FileName, RefNum);
  3115.                     exit(ImportFile);
  3116.                 end;
  3117.             ImportText:  begin
  3118.                     ImportFile := ImportTextFile(FileName, RefNum);
  3119.                     exit(ImportFile);
  3120.                 end;
  3121.             otherwise;
  3122.         end;
  3123.         if ImportAll then
  3124.             ImportAllFiles(RefNum)
  3125.         else if (WhatToOpen = OpenCustom) and (ImportCustomDepth <> EightBits) then
  3126.             b := Import16BitFile(FileName, RefNum)
  3127.         else
  3128.             b := OpenFile(FileName, RefNum);
  3129.         if macro then
  3130.             GenerateValues;
  3131.         if ImportingTIFF then
  3132.             WhatToImport := ImportTiff; {GetTIFFParameters may have changed it to ImportCustom.}
  3133.     end;
  3134.  
  3135.  
  3136.     procedure RevertToSaved;
  3137.         var
  3138.             fname: str255;
  3139.             err, f: integer;
  3140.             ok: boolean;
  3141.             size: LongInt;
  3142.     begin
  3143.         if OpPending then
  3144.             KillRoi;
  3145.         DisableDensitySlice;
  3146.         with Info^ do begin
  3147.                 fname := title;
  3148.                 SetPort(wptr);
  3149.                 if PictureType = PICTFile then begin
  3150.                         ok := OpenPICT(fname, vref, true);
  3151.                         UpdatePicWindow;
  3152.                     end
  3153.                 else begin
  3154.                         ShowWatch;
  3155.                         err := fsopen(fname, vref, f);
  3156.                         ok := true;
  3157.                         if HeaderOffset <> -1 then
  3158.                             ok := OpenImageHeader(f, fname, vref);
  3159.                         if ok then begin
  3160.                                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  3161.                                 size := ImageSize;
  3162.                                 CheckFileSize(f, size, ImageDataOffset);
  3163.                                 if size > 0 then
  3164.                                     err := fsread(f, size, PicBaseAddr);
  3165.                                 if odd(PixelsPerLine) then
  3166.                                     UnpackLines;
  3167.                                 if Info^.InvertedImage then
  3168.                                     InvertPic;
  3169.                                 UpdatePicWindow;
  3170.                             end;
  3171.                         err := fsclose(f);
  3172.                         RoiShowing := false;
  3173.                     end;
  3174.                 OpPending := false;
  3175.                 Changes := false;
  3176.                 UpdateTitleBar;
  3177.             end; {with}
  3178.     end;
  3179.  
  3180.  
  3181.     procedure FindWhatToPrint;
  3182.         var
  3183.             kind: integer;
  3184.             WhichWindow: WindowPtr;
  3185.     begin
  3186.         WhatToPrint := NothingToPrint;
  3187.         WhichWindow := FrontWindow;
  3188.         if WhichWindow = nil then
  3189.             exit(FindWhatToPrint);
  3190.         kind := WindowPeek(WhichWindow)^.WindowKind;
  3191.         if (kind = PicKind) and info^.RoiShowing and measuring then
  3192.             kind := InfoKind;
  3193.         case kind of
  3194.             PicKind: 
  3195.                 if info^.RoiShowing then
  3196.                     WhatToPrint := PrintSelection
  3197.                 else
  3198.                     WhatToPRint := PrintImage;
  3199.             HistoKind: 
  3200.                 WhatToPrint := PrintHistogram;
  3201.             ProfilePlotKind, CalibrationPlotKind: 
  3202.                 WhatToPrint := PrintPlot;
  3203.             InfoKind, ResultsKind: 
  3204.                 if mCount > 0 then
  3205.                     WhatToPrint := PrintMeasurements;
  3206.             TextKind: 
  3207.                 WhatToPrint := PrintText;
  3208.             otherwise
  3209.                 ;
  3210.         end;
  3211.         if (WhatToPrint = NothingToPRint) and (info <> NoInfo) then
  3212.             WhatToPrint := PrintImage;
  3213.     end;
  3214.  
  3215.  
  3216.     procedure UpdateFileMenu;
  3217.         var
  3218.             ShowItems, isSelection, notStack: boolean;
  3219.             i: integer;
  3220.             str, str2: str255;
  3221.     begin
  3222.         with info^ do begin
  3223.                 ShowItems := Info <> NoInfo;
  3224.                 isSelection := RoiShowing and (RoiType = RectRoi);
  3225.                 notStack := StackInfo = nil;
  3226.                 if OptionKeyWasDown and (CurrentKind <> TextKind) then begin
  3227.                         SetMenuItemText(FileMenuH, CloseItem, 'Close All…');
  3228.                         SetMenuItemText(FileMenuH, SaveItem, 'Save All');
  3229.                         SetMenuItem(FileMenuH, CloseItem, ShowItems);
  3230.                     end
  3231.                 else begin
  3232.                         SetMenuItemText(FileMenuH, CloseItem, 'Close…');
  3233.                         if isSelection and notStack and (CurrentKind <> TextKind) and (PictureType <> TiffFile) and (PictureType <> PictFile) and (CurrentKind = PicKind) then
  3234.                             SetMenuItemText(FileMenuH, SaveItem, 'Save Selection')
  3235.                         else
  3236.                             SetMenuItemText(FileMenuH, SaveItem, 'Save');
  3237.                         SetMenuItem(FileMenuH, CloseItem, ShowItems or (CurrentKind = TextKind) or (CurrentKind = ResultsKind) or (CurrentKind = ProfilePlotKind) or (CurrentKind = CalibrationPlotKind) or (CurrentKind = HistoKind));
  3238.                     end;
  3239.                 case CurrentKind of
  3240.                     ProfilePlotKind, CalibrationPlotKind: 
  3241.                         ExportAsWhat := asPlotValues;
  3242.                     HistoKind: 
  3243.                         ExportAsWhat := asHistogramValues;
  3244.                     ResultsKind: 
  3245.                         ExportAsWhat := asMeasurements;
  3246.                     PicKind:  begin
  3247.                             if (SaveAsWhat <> asPICT) then
  3248.                                 SaveAsWhat := asTiff;
  3249.                             if (ExportAsWhat > asText) then
  3250.                                 ExportAsWhat := asRaw;
  3251.                         end;
  3252.                     otherwise
  3253.                 end;
  3254.                 if isSelection and notStack and (SaveAsWhat <> AsPalette) and (CurrentKind <> ResultsKind) and (CurrentKind <> TextKind) then
  3255.                     SetMenuItemText(FileMenuH, SaveAsItem, 'Save Selection As…')
  3256.                 else
  3257.                     SetMenuItemText(FileMenuH, SaveAsItem, 'Save As…');
  3258.                 if isSelection and notStack and (ExportAsWhat <= AsText) then
  3259.                     SetMenuItemText(FileMenuH, ExportItem, 'Export Selection As…')
  3260.                 else
  3261.                     SetMenuItemText(FileMenuH, ExportItem, 'Export…');
  3262.                 for i := SaveItem to SaveAsItem do
  3263.                     SetMenuItem(FileMenuH, i, ShowItems or (CurrentKind = TextKind));
  3264.                 SetMenuItem(FileMenuH, ExportItem, (ShowItems or (CurrentKind = ResultsKind)) and (CurrentKind <> TextKind));
  3265.                 if isSelection then
  3266.                     str := 'Duplicate Selection'
  3267.                 else
  3268.                     str := 'Duplicate';
  3269.                 SetMenuItemText(FileMenuH, DuplicateItem, str);
  3270.                 for i := DuplicateItem to GetInfoItem do
  3271.                     SetMenuItem(FileMenuH, i, ShowItems and (CurrentKind <> TextKind));
  3272.                 if DataType <> EightBits then
  3273.                     str := 'Rescale'
  3274.                 else
  3275.                     str := 'Revert to Saved';
  3276.                 SetMenuItemText(FileMenuH, RevertItem, str);
  3277.                 SetMenuItem(FileMenuH, RevertItem, (Revertable or (DataType <> EightBits)) and (CurrentKind <> TextKind));
  3278.                 SetMenuItem(FileMenuH, PlugInExportItem, ShowItems);
  3279.                 FindWhatToPrint;
  3280.                 case WhatToPrint of
  3281.                     NothingToPrint: 
  3282.                         str := '';
  3283.                     PrintImage: 
  3284.                         str := 'Image';
  3285.                     PrintSelection: 
  3286.                         str := 'Selection';
  3287.                     PrintPlot: 
  3288.                         str := 'Plot';
  3289.                     PrintHistogram: 
  3290.                         str := 'Histogram';
  3291.                     PrintMeasurements: 
  3292.                         str := 'Results';
  3293.                     PrintText: 
  3294.                         str := 'Text';
  3295.                 end;
  3296.                 SetMenuItemText(FileMenuH, PrintItem, concat('Print ', str, '…'));
  3297.                 SetMenuItem(FileMenuH, PrintItem, WhatToPrint <> NothingToPrint);
  3298.             end; {with info^}
  3299.     end;
  3300.  
  3301.  
  3302.     procedure SaveAll;
  3303.         var
  3304.             SaveInfo: InfoPtr;
  3305.             i: integer;
  3306.     begin
  3307.         SaveInfo := Info;
  3308.         SaveAsWhat := AsTiff;
  3309.         SaveAllState := SaveAllStage1;
  3310.         for i := 1 to nPics do begin
  3311.                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  3312.                 SaveAs('', 0);
  3313.                 if CommandPeriod or (SaveAllState = NoSaveAll) then
  3314.                     leave;
  3315.             end;
  3316.         Info := SaveInfo;
  3317.         SaveAllState := NoSaveAll;
  3318.     end;
  3319.  
  3320.  
  3321.     function SuggestedExportName: str255;
  3322.         var
  3323.             name: str255;
  3324.     begin
  3325.         name := info^.title;
  3326.         case ExportAsWhat of
  3327.             asRaw, asMCID, asText:  begin
  3328.                     if name = 'Camera' then
  3329.                         name := 'Untitled';
  3330.                     if ExportAsWhat = AsText then
  3331.                         SuggestedExportName := concat(name, ' (Text)')
  3332.                     else
  3333.                         SuggestedExportName := name;
  3334.                 end;
  3335.             AsLUT: 
  3336.                 SuggestedExportName := 'Palette';
  3337.             asMeasurements: 
  3338.                 SuggestedExportName := concat(name, ' (Measurements)');
  3339.             AsPlotValues: 
  3340.                 SuggestedExportName := concat(name, ' (Plot Values)');
  3341.             asHistogramValues: 
  3342.                 SuggestedExportName := concat(name, ' (Histogram)');
  3343.             asCoordinates: 
  3344.                 SuggestedExportName := concat(name, ' (Coordinates)');
  3345.         end;
  3346.     end;
  3347.  
  3348.  
  3349.     function ExportHook (item: integer; theDialog: DialogPtr): integer;
  3350.         const
  3351.             EditTextID = 7;
  3352.             RawID = 9;
  3353.             xyCoordinatesID = 16;
  3354.         var
  3355.             i: integer;
  3356.             fname: str255;
  3357.             NameEdited: boolean;
  3358.     begin
  3359.         if item = -1 then {Initialize}
  3360.             SetDlogItem(theDialog, RawID + ord(ExportAsWhat), 1);
  3361.         fname := GetDString(theDialog, EditTextID);
  3362.         NameEdited := fname <> SuggestedExportName;
  3363.         if (item >= RawID) and (item <= xyCoordinatesID) then begin
  3364.                 ExportAsWhat := ExportAsWhatType(item - RawID);
  3365.                 if not NameEdited then begin
  3366.                         SetDString(theDialog, EditTextID, SuggestedExportName);
  3367.                         SelectdialogItemText(theDialog, EditTextID, 0, 32767);
  3368.                     end;
  3369.                 for i := RawID to xyCoordinatesID do
  3370.                     SetDlogItem(theDialog, i, 0);
  3371.                 SetDlogItem(theDialog, item, 1);
  3372.             end;
  3373.         ExportHook := item;
  3374.     end;
  3375.  
  3376.  
  3377.     procedure Export (name: str255; RefNum: integer);
  3378.         const
  3379.             CustomDialogID = 100;
  3380.         var
  3381.             where: Point;
  3382.             reply: SFReply;
  3383.             isSelection: boolean;
  3384.             kind: integer;
  3385.             SaveAsState: SaveAsWhatType;
  3386.     begin
  3387.         if ExportDHookProc=nil
  3388.             then ExportDHookProc:=NewRoutineDescriptor(@ExportHook, uppDlgHookProcInfo, GetCurrentISA);
  3389.         with info^ do begin
  3390.                 if (name = '') or ((RefNum = 0) and (pos(':', name) = 0)) then begin
  3391.                         where.v := 50;
  3392.                         where.h := 50;
  3393.                         if name = '' then
  3394.                             name := SuggestedExportName;
  3395.                         SFPPutFile(Where, 'Save as?', name, ExportDHookProc, reply, CustomDialogID, nil);
  3396.                         if not reply.good then begin
  3397.                                 AbortMacro;
  3398.                                 exit(Export);
  3399.                             end;
  3400.                         with reply do begin
  3401.                                 name := fname;
  3402.                                 RefNum := vRefNum;
  3403.                                 DefaultRefNum := RefNum;
  3404.                             end;
  3405.                     end;
  3406.                 if (Info = NoInfo) and (ExportAsWhat <= asText) then begin
  3407.                     PutError('No image data available.');
  3408.                     AbortMacro;
  3409.                     exit(Export);
  3410.                 end;
  3411.                 isSelection := RoiShowing and (RoiType = RectRoi);
  3412.                 case ExportAsWhat of
  3413.                     asRaw, asMCID:  begin
  3414.                             if ExportAsWhat = asMCID then
  3415.                                 InvertPic;
  3416.                             SaveAsState := SaveAsWhat;
  3417.                             if ExportAsWhat = AsRaw then
  3418.                                 SaveAsWhat := asRawData
  3419.                             else
  3420.                                 SaveAsWhat := SaveAsMCID;
  3421.                             if isSelection then
  3422.                                 SaveSelection(name, RefNum, false)
  3423.                             else
  3424.                                 SaveAsTIFF(name, RefNum, 0, 0, false);
  3425.                             SaveAsWhat := SaveAsState;
  3426.                         end;
  3427.                     AsText: 
  3428.                         ExportAsText(name, RefNum);
  3429.                     AsLUT: 
  3430.                         SaveLUT(name, RefNum);
  3431.                     asMeasurements: 
  3432.                         if mCount > 0 then
  3433.                             ExportMeasurements(name, RefNum)
  3434.                         else
  3435.                             PutError('Sorry, but no measurements are available to export.');
  3436.                     AsPlotValues: 
  3437.                         if PlotWindow <> nil then begin
  3438.                                 kind := WindowPeek(PlotWindow)^.WindowKind;
  3439.                                 case kind of
  3440.                                     ProfilePlotKind: 
  3441.                                         ConvertPlotToText;
  3442.                                     CalibrationPlotKind: 
  3443.                                         ConvertCalibrationCurveToText;
  3444.                                     otherwise
  3445.                                         TextBufSize := 0;
  3446.                                 end;
  3447.                                 SaveAsText(name, RefNum);
  3448.                             end
  3449.                         else
  3450.                             beep;
  3451.                     asHistogramValues: 
  3452.                         if HistoWindow <> nil then begin
  3453.                                 ConvertHistoToText;
  3454.                                 SaveAsText(name, RefNum);
  3455.                             end
  3456.                         else
  3457.                             beep;
  3458.                     asCoordinates: 
  3459.                         ExportCoordinates(name, RefNum);
  3460.                     otherwise
  3461.                         beep;
  3462.                 end; {case}
  3463.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  3464.                     SaveAsWhat := asTIFF;
  3465.             end; {with}
  3466.     end;
  3467.  
  3468.  
  3469.  
  3470. end.